Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
  [S390] remove __io_virt and mmiowb.
  [S390] cio: use ARRAY_SIZE in device_id.c
  [S390] cio: Fixup interface for setting options on ccw devices.
  [S390] smp_call_function/smp_call_function_on locking.
diff --git a/Documentation/drivers/edac/edac.txt b/Documentation/drivers/edac/edac.txt
index 7b3d969..3c5a9e4 100644
--- a/Documentation/drivers/edac/edac.txt
+++ b/Documentation/drivers/edac/edac.txt
@@ -339,7 +339,21 @@
 
 	'device'
 
-	Symlink to the memory controller device
+	Symlink to the memory controller device.
+
+Sdram memory scrubbing rate:
+
+	'sdram_scrub_rate'
+
+	Read/Write attribute file that controls memory scrubbing. The scrubbing
+	rate is set by writing a minimum bandwith in bytes/sec to the attribute
+	file. The rate will be translated to an internal value that gives at
+	least the specified rate.
+
+	Reading the file will return the actual scrubbing rate employed.
+
+	If configuration fails or memory scrubbing is not implemented, the value
+	of the attribute file will be -1.
 
 
 
diff --git a/Documentation/fb/s3fb.txt b/Documentation/fb/s3fb.txt
new file mode 100644
index 0000000..8a04c0d
--- /dev/null
+++ b/Documentation/fb/s3fb.txt
@@ -0,0 +1,78 @@
+
+	s3fb - fbdev driver for S3 Trio/Virge chips
+	===========================================
+
+
+Supported Hardware
+==================
+
+	S3 Trio32
+	S3 Trio64 (and variants V+, UV+, V2/DX, V2/GX)
+	S3 Virge  (and variants VX, DX, GX and GX2+)
+	S3 Plato/PX		(completely untested)
+	S3 Aurora64V+		(completely untested)
+
+	- only PCI bus supported
+	- only BIOS initialized VGA devices supported
+	- probably not working on big endian
+
+I tested s3fb on Trio64 (plain, V+ and V2/DX) and Virge (plain, VX, DX),
+all on i386.
+
+
+Supported Features
+==================
+
+	*  4 bpp pseudocolor modes (with 18bit palette, two variants)
+	*  8 bpp pseudocolor mode (with 18bit palette)
+	* 16 bpp truecolor modes (RGB 555 and RGB 565)
+	* 24 bpp truecolor mode (RGB 888) on (only on Virge VX)
+	* 32 bpp truecolor mode (RGB 888) on (not on Virge VX)
+	* text mode (activated by bpp = 0)
+	* interlaced mode variant (not available in text mode)
+	* doublescan mode variant (not available in text mode)
+	* panning in both directions
+	* suspend/resume support
+	* DPMS support
+
+Text mode is supported even in higher resolutions, but there is limitation
+to lower pixclocks (maximum between 50-60 MHz, depending on specific hardware).
+This limitation is not enforced by driver. Text mode supports 8bit wide fonts
+only (hardware limitation) and 16bit tall fonts (driver limitation).
+
+There are two 4 bpp modes. First mode (selected if nonstd == 0) is mode with
+packed pixels, high nibble first. Second mode (selected if nonstd == 1) is mode
+with interleaved planes (1 byte interleave), MSB first. Both modes support
+8bit wide fonts only (driver limitation).
+
+Suspend/resume works on systems that initialize video card during resume and
+if device is active (for example used by fbcon).
+
+
+Missing Features
+================
+(alias TODO list)
+
+	* secondary (not initialized by BIOS) device support
+   	* big endian support
+	* Zorro bus support
+	* MMIO support
+	* 24 bpp mode support on more cards
+	* support for fontwidths != 8 in 4 bpp modes
+	* support for fontheight != 16 in text mode
+	* composite and external sync (is anyone able to test this?)
+	* hardware cursor
+	* video overlay support
+	* vsync synchronization
+	* feature connector support
+	* acceleration support (8514-like 2D, Virge 3D, busmaster transfers)
+	* better values for some magic registers (performance issues)
+
+
+Known bugs
+==========
+
+	* cursor disable in text mode doesn't work
+
+--
+Ondrej Zajicek <santiago@crfreenet.org>
diff --git a/Documentation/filesystems/ufs.txt b/Documentation/filesystems/ufs.txt
index 2b5a56a..7a602ad 100644
--- a/Documentation/filesystems/ufs.txt
+++ b/Documentation/filesystems/ufs.txt
@@ -21,7 +21,7 @@
 		supported as read-write
 
 	ufs2    used in FreeBSD 5.x
-		supported as read-only
+		supported as read-write
 
 	5xbsd	synonym for ufs2
 
@@ -50,12 +50,11 @@
 POSSIBLE PROBLEMS
 =================
 
-There is still bug in reallocation of fragment, in file fs/ufs/balloc.c, 
-line 364. But it seems working on current buffer cache configuration.
+See next section, if you have any.
 
 
 BUG REPORTS
 ===========
 
-Any ufs bug report you can send to daniel.pirkl@email.cz (do not send 
-partition tables bug reports.)
+Any ufs bug report you can send to daniel.pirkl@email.cz or
+to dushistov@mail.ru (do not send partition tables bug reports).
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
new file mode 100644
index 0000000..09dd510
--- /dev/null
+++ b/Documentation/gpio.txt
@@ -0,0 +1,271 @@
+GPIO Interfaces
+
+This provides an overview of GPIO access conventions on Linux.
+
+
+What is a GPIO?
+===============
+A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
+digital signal.  They are provided from many kinds of chip, and are familiar
+to Linux developers working with embedded and custom hardware.  Each GPIO
+represents a bit connected to a particular pin, or "ball" on Ball Grid Array
+(BGA) packages.  Board schematics show which external hardware connects to
+which GPIOs.  Drivers can be written generically, so that board setup code
+passes such pin configuration data to drivers.
+
+System-on-Chip (SOC) processors heavily rely on GPIOs.  In some cases, every
+non-dedicated pin can be configured as a GPIO; and most chips have at least
+several dozen of them.  Programmable logic devices (like FPGAs) can easily
+provide GPIOs; multifunction chips like power managers, and audio codecs
+often have a few such pins to help with pin scarcity on SOCs; and there are
+also "GPIO Expander" chips that connect using the I2C or SPI serial busses.
+Most PC southbridges have a few dozen GPIO-capable pins (with only the BIOS
+firmware knowing how they're used).
+
+The exact capabilities of GPIOs vary between systems.  Common options:
+
+  - Output values are writable (high=1, low=0).  Some chips also have
+    options about how that value is driven, so that for example only one
+    value might be driven ... supporting "wire-OR" and similar schemes
+    for the other value.
+
+  - Input values are likewise readable (1, 0).  Some chips support readback
+    of pins configured as "output", which is very useful in such "wire-OR"
+    cases (to support bidirectional signaling).  GPIO controllers may have
+    input de-glitch logic, sometimes with software controls.
+
+  - Inputs can often be used as IRQ signals, often edge triggered but
+    sometimes level triggered.  Such IRQs may be configurable as system
+    wakeup events, to wake the system from a low power state.
+
+  - Usually a GPIO will be configurable as either input or output, as needed
+    by different product boards; single direction ones exist too.
+
+  - Most GPIOs can be accessed while holding spinlocks, but those accessed
+    through a serial bus normally can't.  Some systems support both types.
+
+On a given board each GPIO is used for one specific purpose like monitoring
+MMC/SD card insertion/removal, detecting card writeprotect status, driving
+a LED, configuring a transceiver, bitbanging a serial bus, poking a hardware
+watchdog, sensing a switch, and so on.
+
+
+GPIO conventions
+================
+Note that this is called a "convention" because you don't need to do it this
+way, and it's no crime if you don't.  There **are** cases where portability
+is not the main issue; GPIOs are often used for the kind of board-specific
+glue logic that may even change between board revisions, and can't ever be
+used on a board that's wired differently.  Only least-common-denominator
+functionality can be very portable.  Other features are platform-specific,
+and that can be critical for glue logic.
+
+Plus, this doesn't define an implementation framework, just an interface.
+One platform might implement it as simple inline functions accessing chip
+registers; another might implement it by delegating through abstractions
+used for several very different kinds of GPIO controller.
+
+That said, if the convention is supported on their platform, drivers should
+use it when possible:
+
+	#include <asm/gpio.h>
+
+If you stick to this convention then it'll be easier for other developers to
+see what your code is doing, and help maintain it.
+
+
+Identifying GPIOs
+-----------------
+GPIOs are identified by unsigned integers in the range 0..MAX_INT.  That
+reserves "negative" numbers for other purposes like marking signals as
+"not available on this board", or indicating faults.
+
+Platforms define how they use those integers, and usually #define symbols
+for the GPIO lines so that board-specific setup code directly corresponds
+to the relevant schematics.  In contrast, drivers should only use GPIO
+numbers passed to them from that setup code, using platform_data to hold
+board-specific pin configuration data (along with other board specific
+data they need).  That avoids portability problems.
+
+So for example one platform uses numbers 32-159 for GPIOs; while another
+uses numbers 0..63 with one set of GPIO controllers, 64-79 with another
+type of GPIO controller, and on one particular board 80-95 with an FPGA.
+The numbers need not be contiguous; either of those platforms could also
+use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders.
+
+Whether a platform supports multiple GPIO controllers is currently a
+platform-specific implementation issue.
+
+
+Using GPIOs
+-----------
+One of the first things to do with a GPIO, often in board setup code when
+setting up a platform_device using the GPIO, is mark its direction:
+
+	/* set as input or output, returning 0 or negative errno */
+	int gpio_direction_input(unsigned gpio);
+	int gpio_direction_output(unsigned gpio);
+
+The return value is zero for success, else a negative errno.  It should
+be checked, since the get/set calls don't have error returns and since
+misconfiguration is possible.  (These calls could sleep.)
+
+Setting the direction can fail if the GPIO number is invalid, or when
+that particular GPIO can't be used in that mode.  It's generally a bad
+idea to rely on boot firmware to have set the direction correctly, since
+it probably wasn't validated to do more than boot Linux.  (Similarly,
+that board setup code probably needs to multiplex that pin as a GPIO,
+and configure pullups/pulldowns appropriately.)
+
+
+Spinlock-Safe GPIO access
+-------------------------
+Most GPIO controllers can be accessed with memory read/write instructions.
+That doesn't need to sleep, and can safely be done from inside IRQ handlers.
+
+Use these calls to access such GPIOs:
+
+	/* GPIO INPUT:  return zero or nonzero */
+	int gpio_get_value(unsigned gpio);
+
+	/* GPIO OUTPUT */
+	void gpio_set_value(unsigned gpio, int value);
+
+The values are boolean, zero for low, nonzero for high.  When reading the
+value of an output pin, the value returned should be what's seen on the
+pin ... that won't always match the specified output value, because of
+issues including wire-OR and output latencies.
+
+The get/set calls have no error returns because "invalid GPIO" should have
+been reported earlier in gpio_set_direction().  However, note that not all
+platforms can read the value of output pins; those that can't should always
+return zero.  Also, these calls will be ignored for GPIOs that can't safely
+be accessed wihtout sleeping (see below).
+
+Platform-specific implementations are encouraged to optimise the two
+calls to access the GPIO value in cases where the GPIO number (and for
+output, value) are constant.  It's normal for them to need only a couple
+of instructions in such cases (reading or writing a hardware register),
+and not to need spinlocks.  Such optimized calls can make bitbanging
+applications a lot more efficient (in both space and time) than spending
+dozens of instructions on subroutine calls.
+
+
+GPIO access that may sleep
+--------------------------
+Some GPIO controllers must be accessed using message based busses like I2C
+or SPI.  Commands to read or write those GPIO values require waiting to
+get to the head of a queue to transmit a command and get its response.
+This requires sleeping, which can't be done from inside IRQ handlers.
+
+Platforms that support this type of GPIO distinguish them from other GPIOs
+by returning nonzero from this call:
+
+	int gpio_cansleep(unsigned gpio);
+
+To access such GPIOs, a different set of accessors is defined:
+
+	/* GPIO INPUT:  return zero or nonzero, might sleep */
+	int gpio_get_value_cansleep(unsigned gpio);
+
+	/* GPIO OUTPUT, might sleep */
+	void gpio_set_value_cansleep(unsigned gpio, int value);
+
+Other than the fact that these calls might sleep, and will not be ignored
+for GPIOs that can't be accessed from IRQ handlers, these calls act the
+same as the spinlock-safe calls.
+
+
+Claiming and Releasing GPIOs (OPTIONAL)
+---------------------------------------
+To help catch system configuration errors, two calls are defined.
+However, many platforms don't currently support this mechanism.
+
+	/* request GPIO, returning 0 or negative errno.
+	 * non-null labels may be useful for diagnostics.
+	 */
+	int gpio_request(unsigned gpio, const char *label);
+
+	/* release previously-claimed GPIO */
+	void gpio_free(unsigned gpio);
+
+Passing invalid GPIO numbers to gpio_request() will fail, as will requesting
+GPIOs that have already been claimed with that call.  The return value of
+gpio_request() must be checked.  (These calls could sleep.)
+
+These calls serve two basic purposes.  One is marking the signals which
+are actually in use as GPIOs, for better diagnostics; systems may have
+several hundred potential GPIOs, but often only a dozen are used on any
+given board.  Another is to catch conflicts between drivers, reporting
+errors when drivers wrongly think they have exclusive use of that signal.
+
+These two calls are optional because not not all current Linux platforms
+offer such functionality in their GPIO support; a valid implementation
+could return success for all gpio_request() calls.  Unlike the other calls,
+the state they represent doesn't normally match anything from a hardware
+register; it's just a software bitmap which clearly is not necessary for
+correct operation of hardware or (bug free) drivers.
+
+Note that requesting a GPIO does NOT cause it to be configured in any
+way; it just marks that GPIO as in use.  Separate code must handle any
+pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).
+
+
+GPIOs mapped to IRQs
+--------------------
+GPIO numbers are unsigned integers; so are IRQ numbers.  These make up
+two logically distinct namespaces (GPIO 0 need not use IRQ 0).  You can
+map between them using calls like:
+
+	/* map GPIO numbers to IRQ numbers */
+	int gpio_to_irq(unsigned gpio);
+
+	/* map IRQ numbers to GPIO numbers */
+	int irq_to_gpio(unsigned irq);
+
+Those return either the corresponding number in the other namespace, or
+else a negative errno code if the mapping can't be done.  (For example,
+some GPIOs can't used as IRQs.)  It is an unchecked error to use a GPIO
+number that hasn't been marked as an input using gpio_set_direction(), or
+to use an IRQ number that didn't originally come from gpio_to_irq().
+
+These two mapping calls are expected to cost on the order of a single
+addition or subtraction.  They're not allowed to sleep.
+
+Non-error values returned from gpio_to_irq() can be passed to request_irq()
+or free_irq().  They will often be stored into IRQ resources for platform
+devices, by the board-specific initialization code.  Note that IRQ trigger
+options are part of the IRQ interface, e.g. IRQF_TRIGGER_FALLING, as are
+system wakeup capabilities.
+
+Non-error values returned from irq_to_gpio() would most commonly be used
+with gpio_get_value().
+
+
+
+What do these conventions omit?
+===============================
+One of the biggest things these conventions omit is pin multiplexing, since
+this is highly chip-specific and nonportable.  One platform might not need
+explicit multiplexing; another might have just two options for use of any
+given pin; another might have eight options per pin; another might be able
+to route a given GPIO to any one of several pins.  (Yes, those examples all
+come from systems that run Linux today.)
+
+Related to multiplexing is configuration and enabling of the pullups or
+pulldowns integrated on some platforms.  Not all platforms support them,
+or support them in the same way; and any given board might use external
+pullups (or pulldowns) so that the on-chip ones should not be used.
+
+There are other system-specific mechanisms that are not specified here,
+like the aforementioned options for input de-glitching and wire-OR output.
+Hardware may support reading or writing GPIOs in gangs, but that's usually
+configuration dependednt:  for GPIOs sharing the same bank.  (GPIOs are
+commonly grouped in banks of 16 or 32, with a given SOC having several such
+banks.)  Code relying on such mechanisms will necessarily be nonportable.
+
+Dynamic definition of GPIOs is not currently supported; for example, as
+a side effect of configuring an add-on board with some GPIO expanders.
+
+These calls are purely for kernel space, but a userspace API could be built
+on top of it.
diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset
index fa0d4cc..55b2852 100644
--- a/Documentation/isdn/README.gigaset
+++ b/Documentation/isdn/README.gigaset
@@ -8,29 +8,33 @@
      This release supports the connection of the Gigaset 307x/417x family of
      ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB
      connection. The following devices are reported to be compatible:
-     307x/417x:
-        Gigaset SX255isdn
-        Gigaset SX353isdn
-        Sinus 45 [AB] isdn (Deutsche Telekom)
-        Sinus 721X/XA
+
+     Bases:
+        Siemens Gigaset 3070/3075 isdn
+        Siemens Gigaset 4170/4175 isdn
+        Siemens Gigaset SX205/255
+        Siemens Gigaset SX353
+        T-Com Sinus 45 [AB] isdn
+        T-Com Sinus 721X[A] [SE]
         Vox Chicago 390 ISDN (KPN Telecom)
-     M101:
-        Sinus 45 Data 1 (Telekom)
-     M105:
-        Gigaset USB Adapter DECT
-        Sinus 45 Data 2 (Telekom)
-        Sinus 721 data
+
+     RS232 data boxes:
+        Siemens Gigaset M101 Data
+        T-Com Sinus 45 Data 1
+
+     USB data boxes:
+        Siemens Gigaset M105 Data
+        Siemens Gigaset USB Adapter DECT
+        T-Com Sinus 45 Data 2
+        T-Com Sinus 721 data
         Chicago 390 USB (KPN)
+
      See also http://www.erbze.info/sinus_gigaset.htm and
               http://gigaset307x.sourceforge.net/
 
      We had also reports from users of Gigaset M105 who could use the drivers
      with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.4.)
      If you have another device that works with our driver, please let us know.
-     For example, Gigaset SX205isdn/Sinus 721 X SE and Gigaset SX303isdn bases
-     are just versions without answering machine of models known to work, so
-     they should work just as well; but so far we are lacking positive reports
-     on these.
 
      Chances of getting an USB device to work are good if the output of
         lsusb
@@ -60,14 +64,28 @@
      To get the device working, you have to load the proper kernel module. You
      can do this using
          modprobe modulename
-     where modulename is usb_gigaset (M105) or bas_gigaset (direct USB
-     connection to the base).
+     where modulename is ser_gigaset (M101), usb_gigaset (M105), or
+     bas_gigaset (direct USB connection to the base).
+
+     The module ser_gigaset provides a serial line discipline N_GIGASET_M101
+     which drives the device through the regular serial line driver. To use it,
+     run the Gigaset M101 daemon "gigasetm101d" (also available from
+     http://sourceforge.net/projects/gigaset307x/) with the device file of the
+     RS232 port to the M101 as an argument, for example:
+	 gigasetm101d /dev/ttyS1
+     This will open the device file, set its line discipline to N_GIGASET_M101,
+     and then sleep in the background, keeping the device open so that the
+     line discipline remains active. To deactivate it, kill the daemon, for
+     example with
+	 killall gigasetm101d
+     before disconnecting the device.
 
 2.2. Device nodes for user space programs
      ------------------------------------
      The device can be accessed from user space (eg. by the user space tools
      mentioned in 1.2.) through the device nodes:
 
+     - /dev/ttyGS0 for M101 (RS232 data boxes)
      - /dev/ttyGU0 for M105 (USB data boxes)
      - /dev/ttyGB0 for the base driver (direct USB connection)
 
@@ -168,6 +186,19 @@
      You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
      setting (ttyGxy is ttyGU0 or ttyGB0).
 
+2.6. M105 Undocumented USB Requests
+     ------------------------------
+
+     The Gigaset M105 USB data box understands a couple of useful, but
+     undocumented USB commands. These requests are not used in normal
+     operation (for wireless access to the base), but are needed for access
+     to the M105's own configuration mode (registration to the base, baudrate
+     and line format settings, device status queries) via the gigacontr
+     utility. Their use is disabled in the driver by default for safety
+     reasons but can be enabled by setting the kernel configuration option
+     "Support for undocumented USB requests" (GIGASET_UNDOCREQ) to "Y" and
+     recompiling.
+
 
 3.   Troubleshooting
      ---------------
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 0733068..79775a4 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -311,10 +311,10 @@
 loading dump-capture kernel.
 
 For i386, x86_64 and ia64:
-	"init 1 irqpoll maxcpus=1"
+	"1 irqpoll maxcpus=1"
 
 For ppc64:
-	"init 1 maxcpus=1 noirqdistrib"
+	"1 maxcpus=1 noirqdistrib"
 
 
 Notes on loading the dump-capture kernel:
@@ -332,8 +332,8 @@
 * You must specify <root-dev> in the format corresponding to the root
   device name in the output of mount command.
 
-* "init 1" boots the dump-capture kernel into single-user mode without
-  networking. If you want networking, use "init 3."
+* Boot parameter "1" boots the dump-capture kernel into single-user
+  mode without networking. If you want networking, use "3".
 
 * We generally don' have to bring up a SMP kernel just to capture the
   dump. Hence generally it is useful either to build a UP dump-capture
diff --git a/Documentation/nfsroot.txt b/Documentation/nfsroot.txt
index 719f9a9..16a7cae 100644
--- a/Documentation/nfsroot.txt
+++ b/Documentation/nfsroot.txt
@@ -67,8 +67,8 @@
   <nfs-options>	Standard NFS options. All options are separated by commas.
 		The following defaults are used:
 			port		= as given by server portmap daemon
-			rsize		= 1024
-			wsize		= 1024
+			rsize		= 4096
+			wsize		= 4096
 			timeo		= 7
 			retrans		= 3
 			acregmin	= 3
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index 7279579..ecc7c9e 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -284,7 +284,6 @@
 	static struct spi_driver CHIP_driver = {
 		.driver = {
 			.name		= "CHIP",
-			.bus		= &spi_bus_type,
 			.owner		= THIS_MODULE,
 		},
 
@@ -312,7 +311,7 @@
 		chip = kzalloc(sizeof *chip, GFP_KERNEL);
 		if (!chip)
 			return -ENOMEM;
-		dev_set_drvdata(&spi->dev, chip);
+		spi_set_drvdata(spi, chip);
 
 		... etc
 		return 0;
diff --git a/MAINTAINERS b/MAINTAINERS
index 9ea954a..f85c603 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1002,14 +1002,12 @@
 S:	Maintained
 
 CYCLADES ASYNC MUX DRIVER
-M:	async@cyclades.com
 W:	http://www.cyclades.com/
-S:	Supported
+S:	Orphan
 
 CYCLADES PC300 DRIVER
-M:	pc300@cyclades.com
 W:	http://www.cyclades.com/
-S:	Supported
+S:	Orphan
 
 DAMA SLAVE for AX.25
 P:	Joerg Reuter
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 1aea7c7..d352c2b 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -122,7 +122,7 @@
 			 char **, char **);
 static void determine_cpu_caches (unsigned int);
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 /*
  * The format of "screen_info" is strange, and due to early
@@ -547,7 +547,7 @@
 	} else {
 		strlcpy(command_line, COMMAND_LINE, sizeof command_line);
 	}
-	strcpy(saved_command_line, command_line);
+	strcpy(boot_command_line, command_line);
 	*cmdline_p = command_line;
 
 	/* 
@@ -589,7 +589,7 @@
 	}
 
 	/* Replace the command line, now that we've killed it with strsep.  */
-	strcpy(command_line, saved_command_line);
+	strcpy(command_line, boot_command_line);
 
 	/* If we want SRM console printk echoing early, do it now. */
 	if (alpha_using_srm && srmcons_output) {
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index 4e5445c..bf1075e 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -329,7 +329,7 @@
 	return fasync_helper(fd, file, on, &rtc_async_queue);
 }
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= rtc_read,
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index bbab134..ed52215 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -106,7 +106,7 @@
 static struct meminfo meminfo __initdata = { 0, };
 static const char *cpu_name;
 static const char *machine_name;
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
@@ -803,8 +803,8 @@
 	init_mm.end_data   = (unsigned long) &_edata;
 	init_mm.brk	   = (unsigned long) &_end;
 
-	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	parse_cmdline(cmdline_p, from);
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c
index 4dee21f..36a8e4d 100644
--- a/arch/arm/mach-at91rm9200/clock.c
+++ b/arch/arm/mach-at91rm9200/clock.c
@@ -407,7 +407,7 @@
 	return single_open(file, at91_clk_show, NULL);
 }
 
-static struct file_operations at91_clk_operations = {
+static const struct file_operations at91_clk_operations = {
 	.open		= at91_clk_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index af22659..15eb5b6 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -65,6 +65,24 @@
 
 
 /*
+ * mux the pin to the "GPIO" peripheral role.
+ */
+int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio)
+		return -EINVAL;
+	__raw_writel(mask, pio + PIO_IDR);
+	__raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+	__raw_writel(mask, pio + PIO_PER);
+	return 0;
+}
+EXPORT_SYMBOL(at91_set_GPIO_periph);
+
+
+/*
  * mux the pin to the "A" internal peripheral role.
  */
 int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup)
@@ -181,6 +199,36 @@
 
 /*--------------------------------------------------------------------------*/
 
+/* new-style GPIO calls; these expect at91_set_GPIO_periph to have been
+ * called, and maybe at91_set_multi_drive() for putout pins.
+ */
+
+int gpio_direction_input(unsigned pin)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
+		return -EINVAL;
+	__raw_writel(mask, pio + PIO_OER);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned pin)
+{
+	void __iomem	*pio = pin_to_controller(pin);
+	unsigned	mask = pin_to_mask(pin);
+
+	if (!pio || !(__raw_readl(pio + PIO_PSR) & mask))
+		return -EINVAL;
+	__raw_writel(mask, pio + PIO_OER);
+	return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*--------------------------------------------------------------------------*/
+
 /*
  * assuming the pin is muxed as a gpio output, set its value.
  */
diff --git a/arch/arm26/kernel/setup.c b/arch/arm26/kernel/setup.c
index 466ddb5..0e006c6 100644
--- a/arch/arm26/kernel/setup.c
+++ b/arch/arm26/kernel/setup.c
@@ -80,7 +80,7 @@
 static struct meminfo meminfo __initdata = { 0, };
 static struct proc_info_item proc_info;
 static const char *machine_name;
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 
@@ -492,8 +492,8 @@
 	init_mm.end_data   = (unsigned long) &_edata;
 	init_mm.brk	   = (unsigned long) &_end;
 
-	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	parse_cmdline(&meminfo, cmdline_p, from);
 	bootmem_init(&meminfo);
 	paging_init(&meminfo);
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
index c6734ae..a1a7c3c 100644
--- a/arch/avr32/kernel/setup.c
+++ b/arch/avr32/kernel/setup.c
@@ -45,7 +45,7 @@
 };
 EXPORT_SYMBOL(boot_cpu_data);
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 /*
  * Should be more than enough, but if you have a _really_ complex
@@ -202,7 +202,7 @@
 
 static int __init parse_tag_cmdline(struct tag *tag)
 {
-	strlcpy(saved_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
 	return 0;
 }
 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
@@ -294,7 +294,7 @@
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
-	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 	parse_early_param();
 
diff --git a/arch/avr32/mm/tlb.c b/arch/avr32/mm/tlb.c
index 7b07305..5667201 100644
--- a/arch/avr32/mm/tlb.c
+++ b/arch/avr32/mm/tlb.c
@@ -360,7 +360,7 @@
 	return seq_open(file, &tlb_ops);
 }
 
-static struct file_operations proc_tlb_operations = {
+static const struct file_operations proc_tlb_operations = {
 	.open		= tlb_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c
index 3cf4f23..88eff7f 100644
--- a/arch/cris/arch-v10/drivers/ds1302.c
+++ b/arch/cris/arch-v10/drivers/ds1302.c
@@ -499,7 +499,7 @@
 
 /* The various file operations we support. */
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.owner =	THIS_MODULE,
 	.ioctl =	rtc_ioctl,
 }; 
diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c
index 284ebfd..be35a707 100644
--- a/arch/cris/arch-v10/drivers/eeprom.c
+++ b/arch/cris/arch-v10/drivers/eeprom.c
@@ -172,7 +172,7 @@
 static struct eeprom_type eeprom;
 
 /* This is the exported file-operations structure for this device. */
-struct file_operations eeprom_fops =
+const struct file_operations eeprom_fops =
 {
   .llseek  = eeprom_lseek,
   .read    = eeprom_read,
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index 9aba18b..f389ed6 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -838,7 +838,7 @@
 	return 0;
 }
 
-struct file_operations gpio_fops = {
+const struct file_operations gpio_fops = {
 	.owner       = THIS_MODULE,
 	.poll        = gpio_poll,
 	.ioctl       = gpio_ioctl,
diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c
index 092c724..aca81dd 100644
--- a/arch/cris/arch-v10/drivers/i2c.c
+++ b/arch/cris/arch-v10/drivers/i2c.c
@@ -692,7 +692,7 @@
 	return 0;
 }
 
-static struct file_operations i2c_fops = {
+static const struct file_operations i2c_fops = {
 	.owner    = THIS_MODULE,
 	.ioctl    = i2c_ioctl,
 	.open     = i2c_open,
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index 8c830ee..107796e 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -56,7 +56,7 @@
 
 int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 
-static struct file_operations pcf8563_fops = {
+static const struct file_operations pcf8563_fops = {
 	.owner = THIS_MODULE,
 	.ioctl = pcf8563_ioctl,
 };
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index 2449637..1a071f1 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -266,7 +266,7 @@
 
 
 
-struct file_operations cryptocop_fops = {
+const struct file_operations cryptocop_fops = {
 	owner: THIS_MODULE,
 	open: cryptocop_open,
 	release: cryptocop_release,
diff --git a/arch/cris/arch-v32/drivers/gpio.c b/arch/cris/arch-v32/drivers/gpio.c
index 08d36f0..d82c5c5 100644
--- a/arch/cris/arch-v32/drivers/gpio.c
+++ b/arch/cris/arch-v32/drivers/gpio.c
@@ -705,7 +705,7 @@
 	return 0;
 }
 
-struct file_operations gpio_fops = {
+const struct file_operations gpio_fops = {
 	.owner       = THIS_MODULE,
 	.poll        = gpio_poll,
 	.ioctl       = gpio_ioctl,
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c
index 95f0018..5d6c527 100644
--- a/arch/cris/arch-v32/drivers/i2c.c
+++ b/arch/cris/arch-v32/drivers/i2c.c
@@ -573,7 +573,7 @@
 	return 0;
 }
 
-static struct file_operations i2c_fops = {
+static const struct file_operations i2c_fops = {
 	owner:    THIS_MODULE,
 	ioctl:    i2c_ioctl,
 	open:     i2c_open,
diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c
index 2fc7d75..544ab01 100644
--- a/arch/cris/arch-v32/drivers/pcf8563.c
+++ b/arch/cris/arch-v32/drivers/pcf8563.c
@@ -50,7 +50,7 @@
 int pcf8563_open(struct inode *, struct file *);
 int pcf8563_release(struct inode *, struct file *);
 
-static struct file_operations pcf8563_fops = {
+static const struct file_operations pcf8563_fops = {
 	owner: THIS_MODULE,
 	ioctl: pcf8563_ioctl,
 	open: pcf8563_open,
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c
index 424eb0e..df89298 100644
--- a/arch/cris/arch-v32/drivers/sync_serial.c
+++ b/arch/cris/arch-v32/drivers/sync_serial.c
@@ -187,7 +187,7 @@
 
 #define NUMBER_OF_PORTS (sizeof(ports)/sizeof(sync_port))
 
-static struct file_operations sync_serial_fops = {
+static const struct file_operations sync_serial_fops = {
 	.owner   = THIS_MODULE,
 	.write   = sync_serial_write,
 	.read    = sync_serial_read,
diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c
index f60ab78..4cfcae6 100644
--- a/arch/cris/kernel/profile.c
+++ b/arch/cris/kernel/profile.c
@@ -50,7 +50,7 @@
   memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE);
 }
 
-static struct file_operations cris_proc_profile_operations = {
+static const struct file_operations cris_proc_profile_operations = {
 	.read		= read_cris_profile,
 	.write		= write_cris_profile,
 };
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index ca8b45a..65466c4 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -29,7 +29,7 @@
 extern int root_mountflags;
 extern char _etext, _edata, _end;
 
-char cris_command_line[COMMAND_LINE_SIZE] = { 0, };
+char __initdata cris_command_line[COMMAND_LINE_SIZE] = { 0, };
 
 extern const unsigned long text_start, edata; /* set by the linker script */
 extern unsigned long dram_start, dram_end;
@@ -153,8 +153,8 @@
 #endif
 
 	/* Save command line for future references. */
-	memcpy(saved_command_line, cris_command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+	memcpy(boot_command_line, cris_command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
 
 	/* give credit for the CRIS port */
 	show_etrax_copyright();
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 1a5eb6c..8ea3ca2 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -110,7 +110,7 @@
 
 struct cpuinfo_frv __nongprelbss boot_cpu_data;
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 char __initdata redboot_command_line[COMMAND_LINE_SIZE];
 
 #ifdef CONFIG_PM
@@ -762,7 +762,7 @@
 	printk("uClinux FR-V port done by Red Hat Inc <dhowells@redhat.com>\n");
 #endif
 
-	memcpy(saved_command_line, redboot_command_line, COMMAND_LINE_SIZE);
+	memcpy(boot_command_line, redboot_command_line, COMMAND_LINE_SIZE);
 
 	determine_cpu();
 	determine_clocks(1);
@@ -803,7 +803,7 @@
 #endif
 
 	/* deal with the command line - RedBoot may have passed one to the kernel */
-	memcpy(command_line, saved_command_line, sizeof(command_line));
+	memcpy(command_line, boot_command_line, sizeof(command_line));
 	*cmdline_p = &command_line[0];
 	parse_cmdline_early(command_line);
 
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
index 6adf8f4..313cd80 100644
--- a/arch/h8300/kernel/setup.c
+++ b/arch/h8300/kernel/setup.c
@@ -54,7 +54,7 @@
 unsigned long memory_start;
 unsigned long memory_end;
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 
 extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
 extern int _ramstart, _ramend;
@@ -154,8 +154,8 @@
 #endif
 	/* Keep a copy of command line */
 	*cmdline_p = &command_line[0];
-	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = 0;
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = 0;
 
 #ifdef DEBUG
 	if (strlen(*cmdline_p)) 
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 19901692..db99a89 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1894,7 +1894,7 @@
 __setup("apm=", apm_setup);
 #endif
 
-static struct file_operations apm_bios_fops = {
+static const struct file_operations apm_bios_fops = {
 	.owner		= THIS_MODULE,
 	.read		= do_read,
 	.poll		= do_poll,
diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c
index 5ae1705..ee771f3 100644
--- a/arch/i386/kernel/cpu/mtrr/if.c
+++ b/arch/i386/kernel/cpu/mtrr/if.c
@@ -339,7 +339,7 @@
 	return single_open(file, mtrr_seq_show, NULL);
 }
 
-static struct file_operations mtrr_fops = {
+static const struct file_operations mtrr_fops = {
 	.owner   = THIS_MODULE,
 	.open	 = mtrr_open, 
 	.read    = seq_read,
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 51130b3..4da75fa 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -148,7 +148,7 @@
 /*
  * File operations we support
  */
-static struct file_operations cpuid_fops = {
+static const struct file_operations cpuid_fops = {
 	.owner = THIS_MODULE,
 	.llseek = cpuid_seek,
 	.read = cpuid_read,
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index edef508..cb9abdf 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -103,7 +103,7 @@
 	movzwl OLD_CL_OFFSET,%esi
 	addl $(OLD_CL_BASE_ADDR),%esi
 2:
-	movl $(saved_command_line - __PAGE_OFFSET),%edi
+	movl $(boot_command_line - __PAGE_OFFSET),%edi
 	movl $(COMMAND_LINE_SIZE/4),%ecx
 	rep
 	movsl
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index c8fa137..381252b 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -451,7 +451,7 @@
 	return ret;
 }
 
-static struct file_operations microcode_fops = {
+static const struct file_operations microcode_fops = {
 	.owner		= THIS_MODULE,
 	.write		= microcode_write,
 	.open		= microcode_open,
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 4a472a1..4e14264 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -230,7 +230,7 @@
 /*
  * File operations we support
  */
-static struct file_operations msr_fops = {
+static const struct file_operations msr_fops = {
 	.owner = THIS_MODULE,
 	.llseek = msr_seek,
 	.read = msr_read,
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 4b31ad7..4694ac9 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -132,7 +132,7 @@
 #define RAMDISK_PROMPT_FLAG		0x8000
 #define RAMDISK_LOAD_FLAG		0x4000	
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 unsigned char __initdata boot_params[PARAM_SIZE];
 
@@ -576,7 +576,7 @@
 		print_memory_map("user");
 	}
 
-	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 
 	max_low_pfn = setup_memory();
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index ce49fe3..c1dca22 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1881,7 +1881,7 @@
 	return seq_open(file, &ioc_seq_ops);
 }
 
-static struct file_operations ioc_fops = {
+static const struct file_operations ioc_fops = {
 	.open    = ioc_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 6c03928..772ba6f 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -413,11 +413,10 @@
 	efi_char16_t *c16;
 	u64 efi_desc_size;
 	char *cp, vendor[100] = "unknown";
-	extern char saved_command_line[];
 	int i;
 
 	/* it's too early to be able to use the standard kernel command line support... */
-	for (cp = saved_command_line; *cp; ) {
+	for (cp = boot_command_line; *cp; ) {
 		if (memcmp(cp, "mem=", 4) == 0) {
 			mem_limit = memparse(cp + 4, &cp);
 		} else if (memcmp(cp, "max_addr=", 9) == 0) {
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 86e144f..9860794 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -621,7 +621,7 @@
 
 
 /* forward declaration */
-static struct file_operations pfm_file_ops;
+static const struct file_operations pfm_file_ops;
 
 /*
  * forward declarations
@@ -2126,7 +2126,7 @@
 
 
 
-static struct file_operations pfm_file_ops = {
+static const struct file_operations pfm_file_ops = {
 	.llseek   = no_llseek,
 	.read     = pfm_read,
 	.write    = pfm_write,
@@ -6596,7 +6596,7 @@
 	return 0;
 }
 
-static struct file_operations pfm_proc_fops = {
+static const struct file_operations pfm_proc_fops = {
 	.open		= pfm_proc_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
index 20bad78..37c876f 100644
--- a/arch/ia64/kernel/sal.c
+++ b/arch/ia64/kernel/sal.c
@@ -194,9 +194,8 @@
 chk_nointroute_opt(void)
 {
 	char *cp;
-	extern char saved_command_line[];
 
-	for (cp = saved_command_line; *cp; ) {
+	for (cp = boot_command_line; *cp; ) {
 		if (memcmp(cp, "nointroute", 10) == 0) {
 			no_int_routing = 1;
 			printk ("no_int_routing on\n");
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index e375a2f..af9f875 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -352,7 +352,7 @@
 	return size;
 }
 
-static struct file_operations salinfo_event_fops = {
+static const struct file_operations salinfo_event_fops = {
 	.open  = salinfo_event_open,
 	.read  = salinfo_event_read,
 };
@@ -568,7 +568,7 @@
 	return count;
 }
 
-static struct file_operations salinfo_data_fops = {
+static const struct file_operations salinfo_data_fops = {
 	.open    = salinfo_log_open,
 	.release = salinfo_log_release,
 	.read    = salinfo_log_read,
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 83c2629..5fa09d1 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -262,7 +262,7 @@
 	 * appropriate after a kernel panic.
 	 */
 	{
-		char *from = strstr(saved_command_line, "crashkernel=");
+		char *from = strstr(boot_command_line, "crashkernel=");
 		unsigned long base, size;
 		if (from) {
 			size = memparse(from + 12, &from);
@@ -463,7 +463,7 @@
 	ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);
 
 	*cmdline_p = __va(ia64_boot_param->command_line);
-	strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
 
 	efi_init();
 	io_port_init();
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index d9d306c..601747b 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -455,7 +455,7 @@
 	return seq_open(file, &sn2_ptc_seq_ops);
 }
 
-static struct file_operations proc_sn2_ptc_operations = {
+static const struct file_operations proc_sn2_ptc_operations = {
 	.open = sn2_ptc_proc_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 3336799..6da9854 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -865,7 +865,7 @@
 	return r;
 }
 
-static struct file_operations sn_hwperf_fops = {
+static const struct file_operations sn_hwperf_fops = {
 	.ioctl = sn_hwperf_ioctl,
 };
 
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index 936205f..d648143 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -64,7 +64,7 @@
 
 extern int root_mountflags;
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 static struct resource data_resource = {
 	.name   = "Kernel data",
@@ -95,8 +95,8 @@
 	int usermem = 0;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
 	memory_start = (unsigned long)CONFIG_MEMORY_START+PAGE_OFFSET;
 	memory_end = memory_start+(unsigned long)CONFIG_MEMORY_SIZE;
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index 15c16b6..a812d03 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -159,7 +159,7 @@
  *	The various file operations we support.
  */
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.ioctl =	rtc_ioctl,
 	.open =		rtc_open,
 	.release =	rtc_release,
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 9af3ee0..42b8fd0 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -256,7 +256,7 @@
 	init_mm.brk = (unsigned long) &_end;
 
 	*cmdline_p = m68k_command_line;
-	memcpy(saved_command_line, *cmdline_p, CL_SIZE);
+	memcpy(boot_command_line, *cmdline_p, CL_SIZE);
 
 	/* Parse the command line for arch-specific options.
 	 * For the m68k, this is currently only "debug=xxx" to enable printing
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index b0e4c08..272d47e 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -147,7 +147,7 @@
  *	The various file operations we support.
  */
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.ioctl =	rtc_ioctl,
 	.open =		rtc_open,
 	.release =	rtc_release,
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 9cf2e4d..d5c25d2 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -44,7 +44,7 @@
 EXPORT_SYMBOL(memory_start);
 EXPORT_SYMBOL(memory_end);
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 
 /* setup some dummy routines */
 static void dummy_waitbut(void)
@@ -231,8 +231,8 @@
 
 	/* Keep a copy of command line */
 	*cmdline_p = &command_line[0];
-	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = 0;
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = 0;
 
 #ifdef DEBUG
 	if (strlen(*cmdline_p))
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index f29e93c6..d92c48e 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -478,7 +478,7 @@
 	return rtlx_write(minor, (void *)buffer, count, 1);
 }
 
-static struct file_operations rtlx_fops = {
+static const struct file_operations rtlx_fops = {
 	.owner =   THIS_MODULE,
 	.open =    file_open,
 	.release = file_release,
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index d2e01e7..394540f 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -452,7 +452,7 @@
 	print_memory_map();
 
 	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
-	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 
 	*cmdline_p = command_line;
 
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 4e832da..9aca871 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1208,7 +1208,7 @@
 	return ret;
 }
 
-static struct file_operations vpe_fops = {
+static const struct file_operations vpe_fops = {
 	.owner = THIS_MODULE,
 	.open = vpe_open,
 	.release = vpe_release,
diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
index d1a906e..212547c 100644
--- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
+++ b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
@@ -374,7 +374,7 @@
 	return error;
 }
 
-static struct file_operations sbprof_tb_fops = {
+static const struct file_operations sbprof_tb_fops = {
 	.owner		= THIS_MODULE,
 	.open		= sbprof_tb_open,
 	.release	= sbprof_tb_release,
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index ac8ee20..a46bc62 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -479,7 +479,7 @@
 	return error;
 }
 
-static struct file_operations perf_fops = {
+static const struct file_operations perf_fops = {
 	.llseek = no_llseek,
 	.read = perf_read,
 	.write = perf_write,
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 3c7a3fa..74b3686 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -45,7 +45,7 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 
-char	command_line[COMMAND_LINE_SIZE] __read_mostly;
+char	__initdata command_line[COMMAND_LINE_SIZE] __read_mostly;
 
 /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
 struct proc_dir_entry * proc_runway_root __read_mostly = NULL;
@@ -71,9 +71,9 @@
 	/* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */
 	if (boot_args[0] < 64) {
 		/* called from hpux boot loader */
-		saved_command_line[0] = '\0';
+		boot_command_line[0] = '\0';
 	} else {
-		strcpy(saved_command_line, (char *)__va(boot_args[1]));
+		strcpy(boot_command_line, (char *)__va(boot_args[1]));
 
 #ifdef CONFIG_BLK_DEV_INITRD
 		if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
@@ -84,7 +84,7 @@
 #endif
 	}
 
-	strcpy(command_line, saved_command_line);
+	strcpy(command_line, boot_command_line);
 	*cmdline_p = command_line;
 }
 
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 0c118e5..12117db 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -77,12 +77,11 @@
 {
 	char *cp, *end;
 	unsigned long limit;
-	extern char saved_command_line[];
 
 	/* We need this before __setup() functions are called */
 
 	limit = MAX_MEM;
-	for (cp = saved_command_line; *cp; ) {
+	for (cp = boot_command_line; *cp; ) {
 		if (memcmp(cp, "mem=", 4) == 0) {
 			cp += 4;
 			limit = memparse(cp, &end);
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index ec644b3..0345a2c 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -163,6 +163,7 @@
 # CONFIG_PS3_DYNAMIC_DMA is not set
 CONFIG_PS3_USE_LPAR_ADDR=y
 CONFIG_PS3_VUART=y
+CONFIG_PS3_PS3AV=y
 
 #
 # Kernel options
@@ -611,14 +612,40 @@
 # Graphics support
 #
 # CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_IBM_GXT4500 is not set
+CONFIG_FB_PS3=y
+CONFIG_FB_PS3_DEFAULT_SIZE_M=18
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 5e6ddfa..89f46f3 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -498,7 +498,7 @@
 	DBG(" -> check_legacy_serial_console()\n");
 
 	/* The user has requested a console so this is already set up. */
-	if (strstr(saved_command_line, "console=")) {
+	if (strstr(boot_command_line, "console=")) {
 		DBG(" console was specified !\n");
 		return -EBUSY;
 	}
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 0de5a08..89486b6 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -571,7 +571,7 @@
 	return single_open(file, lparcfg_data, NULL);
 }
 
-struct file_operations lparcfg_fops = {
+const struct file_operations lparcfg_fops = {
 	.owner		= THIS_MODULE,
 	.read		= seq_read,
 	.write		= lparcfg_write,
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 869cebb..f9676f5 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -179,7 +179,7 @@
 	}
 }
 
-struct file_operations nvram_fops = {
+const struct file_operations nvram_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	dev_nvram_llseek,
 	.read =		dev_nvram_read,
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index 3d437c3..f78dfce 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -33,7 +33,7 @@
 			      loff_t *ppos);
 static int     page_map_mmap( struct file *file, struct vm_area_struct *vma );
 
-static struct file_operations page_map_fops = {
+static const struct file_operations page_map_fops = {
 	.llseek	= page_map_seek,
 	.read	= page_map_read,
 	.mmap	= page_map_mmap
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 3be52d6..3e86e6e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -991,7 +991,7 @@
 	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
 
 	/* Save command line for /proc/cmdline and then parse parameters */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 	parse_early_param();
 
 	/* Reserve LMB regions used by kernel, initrd, dt, etc... */
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 2fe82ab..6cbf2ae 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -160,7 +160,7 @@
 	return single_open(file, ppc_rtas_sensors_show, NULL);
 }
 
-struct file_operations ppc_rtas_sensors_operations = {
+const struct file_operations ppc_rtas_sensors_operations = {
 	.open		= sensors_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -172,7 +172,7 @@
 	return single_open(file, ppc_rtas_poweron_show, NULL);
 }
 
-struct file_operations ppc_rtas_poweron_operations = {
+const struct file_operations ppc_rtas_poweron_operations = {
 	.open		= poweron_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -185,7 +185,7 @@
 	return single_open(file, ppc_rtas_progress_show, NULL);
 }
 
-struct file_operations ppc_rtas_progress_operations = {
+const struct file_operations ppc_rtas_progress_operations = {
 	.open		= progress_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -198,7 +198,7 @@
 	return single_open(file, ppc_rtas_clock_show, NULL);
 }
 
-struct file_operations ppc_rtas_clock_operations = {
+const struct file_operations ppc_rtas_clock_operations = {
 	.open		= clock_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -211,7 +211,7 @@
 	return single_open(file, ppc_rtas_tone_freq_show, NULL);
 }
 
-struct file_operations ppc_rtas_tone_freq_operations = {
+const struct file_operations ppc_rtas_tone_freq_operations = {
 	.open		= tone_freq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -224,7 +224,7 @@
 	return single_open(file, ppc_rtas_tone_volume_show, NULL);
 }
 
-struct file_operations ppc_rtas_tone_volume_operations = {
+const struct file_operations ppc_rtas_tone_volume_operations = {
 	.open		= tone_volume_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -237,7 +237,7 @@
 	return single_open(file, ppc_rtas_rmo_buf_show, NULL);
 }
 
-struct file_operations ppc_rtas_rmo_buf_ops = {
+const struct file_operations ppc_rtas_rmo_buf_ops = {
 	.open		= rmo_buf_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 65e4ebe..f72118c 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -702,7 +702,7 @@
 }
 
 static struct proc_dir_entry *create_flash_pde(const char *filename,
-					       struct file_operations *fops)
+					       const struct file_operations *fops)
 {
 	struct proc_dir_entry *ent = NULL;
 
@@ -715,21 +715,21 @@
 	return ent;
 }
 
-static struct file_operations rtas_flash_operations = {
+static const struct file_operations rtas_flash_operations = {
 	.read		= rtas_flash_read,
 	.write		= rtas_flash_write,
 	.open		= rtas_excl_open,
 	.release	= rtas_flash_release,
 };
 
-static struct file_operations manage_flash_operations = {
+static const struct file_operations manage_flash_operations = {
 	.read		= manage_flash_read,
 	.write		= manage_flash_write,
 	.open		= rtas_excl_open,
 	.release	= rtas_excl_release,
 };
 
-static struct file_operations validate_flash_operations = {
+static const struct file_operations validate_flash_operations = {
 	.read		= validate_flash_read,
 	.write		= validate_flash_write,
 	.open		= rtas_excl_open,
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 8f5afdb..194a93e 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -150,7 +150,7 @@
 {
 	if (!early_console_initialized)
 		return;
-	if (strstr(saved_command_line, "udbg-immortal")) {
+	if (strstr(boot_command_line, "udbg-immortal")) {
 		printk(KERN_INFO "early console immortal !\n");
 		return;
 	}
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 347eff5..af9e945 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -144,7 +144,7 @@
 	return 0;
 }
 
-static struct file_operations spufs_mem_fops = {
+static const struct file_operations spufs_mem_fops = {
 	.open	 = spufs_mem_open,
 	.read    = spufs_mem_read,
 	.write   = spufs_mem_write,
@@ -249,7 +249,7 @@
 					spufs_cntl_set, "0x%08lx");
 }
 
-static struct file_operations spufs_cntl_fops = {
+static const struct file_operations spufs_cntl_fops = {
 	.open = spufs_cntl_open,
 	.release = simple_attr_close,
 	.read = simple_attr_read,
@@ -309,7 +309,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_regs_fops = {
+static const struct file_operations spufs_regs_fops = {
 	.open	 = spufs_regs_open,
 	.read    = spufs_regs_read,
 	.write   = spufs_regs_write,
@@ -360,7 +360,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_fpcr_fops = {
+static const struct file_operations spufs_fpcr_fops = {
 	.open = spufs_regs_open,
 	.read = spufs_fpcr_read,
 	.write = spufs_fpcr_write,
@@ -426,7 +426,7 @@
 	return count;
 }
 
-static struct file_operations spufs_mbox_fops = {
+static const struct file_operations spufs_mbox_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_mbox_read,
 };
@@ -452,7 +452,7 @@
 	return 4;
 }
 
-static struct file_operations spufs_mbox_stat_fops = {
+static const struct file_operations spufs_mbox_stat_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_mbox_stat_read,
 };
@@ -559,7 +559,7 @@
 	return mask;
 }
 
-static struct file_operations spufs_ibox_fops = {
+static const struct file_operations spufs_ibox_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_ibox_read,
 	.poll	= spufs_ibox_poll,
@@ -585,7 +585,7 @@
 	return 4;
 }
 
-static struct file_operations spufs_ibox_stat_fops = {
+static const struct file_operations spufs_ibox_stat_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_ibox_stat_read,
 };
@@ -692,7 +692,7 @@
 	return mask;
 }
 
-static struct file_operations spufs_wbox_fops = {
+static const struct file_operations spufs_wbox_fops = {
 	.open	= spufs_pipe_open,
 	.write	= spufs_wbox_write,
 	.poll	= spufs_wbox_poll,
@@ -718,7 +718,7 @@
 	return 4;
 }
 
-static struct file_operations spufs_wbox_stat_fops = {
+static const struct file_operations spufs_wbox_stat_fops = {
 	.open	= spufs_pipe_open,
 	.read	= spufs_wbox_stat_read,
 };
@@ -823,7 +823,7 @@
 	return 0;
 }
 
-static struct file_operations spufs_signal1_fops = {
+static const struct file_operations spufs_signal1_fops = {
 	.open = spufs_signal1_open,
 	.read = spufs_signal1_read,
 	.write = spufs_signal1_write,
@@ -934,7 +934,7 @@
 #define spufs_signal2_mmap NULL
 #endif /* !SPUFS_MMAP_4K */
 
-static struct file_operations spufs_signal2_fops = {
+static const struct file_operations spufs_signal2_fops = {
 	.open = spufs_signal2_open,
 	.read = spufs_signal2_read,
 	.write = spufs_signal2_write,
@@ -1037,7 +1037,7 @@
 	return nonseekable_open(inode, file);
 }
 
-static struct file_operations spufs_mss_fops = {
+static const struct file_operations spufs_mss_fops = {
 	.open	 = spufs_mss_open,
 	.mmap	 = spufs_mss_mmap,
 };
@@ -1076,7 +1076,7 @@
 	return nonseekable_open(inode, file);
 }
 
-static struct file_operations spufs_psmap_fops = {
+static const struct file_operations spufs_psmap_fops = {
 	.open	 = spufs_psmap_open,
 	.mmap	 = spufs_psmap_mmap,
 };
@@ -1393,7 +1393,7 @@
 	return fasync_helper(fd, file, on, &ctx->mfc_fasync);
 }
 
-static struct file_operations spufs_mfc_fops = {
+static const struct file_operations spufs_mfc_fops = {
 	.open	 = spufs_mfc_open,
 	.read	 = spufs_mfc_read,
 	.write	 = spufs_mfc_write,
@@ -1650,7 +1650,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_mbox_info_fops = {
+static const struct file_operations spufs_mbox_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_mbox_info_read,
 	.llseek  = generic_file_llseek,
@@ -1688,7 +1688,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_ibox_info_fops = {
+static const struct file_operations spufs_ibox_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_ibox_info_read,
 	.llseek  = generic_file_llseek,
@@ -1729,7 +1729,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_wbox_info_fops = {
+static const struct file_operations spufs_wbox_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_wbox_info_read,
 	.llseek  = generic_file_llseek,
@@ -1779,7 +1779,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_dma_info_fops = {
+static const struct file_operations spufs_dma_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_dma_info_read,
 };
@@ -1830,7 +1830,7 @@
 	return ret;
 }
 
-static struct file_operations spufs_proxydma_info_fops = {
+static const struct file_operations spufs_proxydma_info_fops = {
 	.open = spufs_info_open,
 	.read = spufs_proxydma_info_read,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 738b924..8079983 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -220,11 +220,11 @@
 	return dcache_dir_close(inode, file);
 }
 
-struct inode_operations spufs_dir_inode_operations = {
+const struct inode_operations spufs_dir_inode_operations = {
 	.lookup = simple_lookup,
 };
 
-struct file_operations spufs_context_fops = {
+const struct file_operations spufs_context_fops = {
 	.open		= dcache_dir_open,
 	.release	= spufs_dir_close,
 	.llseek		= dcache_dir_lseek,
@@ -372,7 +372,7 @@
 	return dcache_dir_close(inode, file);
 }
 
-struct file_operations spufs_gang_fops = {
+const struct file_operations spufs_gang_fops = {
 	.open		= dcache_dir_open,
 	.release	= spufs_gang_close,
 	.llseek		= dcache_dir_lseek,
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 70fb133..5686446 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -149,7 +149,7 @@
 		   struct spu_context *ctx, u32 *npc, u32 *status);
 long spufs_create(struct nameidata *nd,
 			 unsigned int flags, mode_t mode);
-extern struct file_operations spufs_context_fops;
+extern const struct file_operations spufs_context_fops;
 
 /* gang management */
 struct spu_gang *alloc_spu_gang(void);
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index c1f4502..91df52a 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -308,7 +308,7 @@
 	return single_open(file, proc_lpevents_show, NULL);
 }
 
-static struct file_operations proc_lpevents_operations = {
+static const struct file_operations proc_lpevents_operations = {
 	.open		= proc_lpevents_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index 90d3d49..b1187d9 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -1224,7 +1224,7 @@
 	return rc;
 }
 
-static struct file_operations proc_vmlinux_operations = {
+static const struct file_operations proc_vmlinux_operations = {
 	.write		= proc_mf_change_vmlinux,
 };
 
diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c
index b54e371..f2cde41 100644
--- a/arch/powerpc/platforms/iseries/proc.c
+++ b/arch/powerpc/platforms/iseries/proc.c
@@ -101,7 +101,7 @@
 	return single_open(file, proc_titantod_show, NULL);
 }
 
-static struct file_operations proc_titantod_operations = {
+static const struct file_operations proc_titantod_operations = {
 	.open		= proc_titantod_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index a6799ed..e2100ec 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -173,7 +173,7 @@
 	return single_open(file, proc_viopath_show, NULL);
 }
 
-static struct file_operations proc_viopath_operations = {
+static const struct file_operations proc_viopath_operations = {
 	.open		= proc_viopath_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index d949e9df..651fa42 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -506,8 +506,8 @@
 	if ((goodness <= current_root_goodness) &&
 	    ROOT_DEV != DEFAULT_ROOT_DEVICE)
 		return;
-	p = strstr(saved_command_line, "root=");
-	if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+	p = strstr(boot_command_line, "root=");
+	if (p != NULL && (p == boot_command_line || p[-1] == ' '))
 		return;
 
 	if (!found_boot) {
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
index de52ec4..4be3943 100644
--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -51,4 +51,15 @@
 	  including the System Manager and AV Settings.  In
 	  general, all users will say Y.
 
+config PS3_PS3AV
+	tristate "PS3 AV settings driver"
+	depends on PPC_PS3
+	select PS3_VUART
+	default y
+	help
+	  Include support for the PS3 AV Settings driver.
+
+	  This support is required for graphics and sound. In
+	  general, all users will say Y or M.
+
 endmenu
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index a4b5a1b..e12e59f 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -2,7 +2,7 @@
  *  PS3 pagetable management routines.
  *
  *  Copyright (C) 2006 Sony Computer Entertainment Inc.
- *  Copyright 2006 Sony Corp.
+ *  Copyright 2006, 2007 Sony Corporation
  *
  *  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
@@ -24,6 +24,7 @@
 #include <asm/lmb.h>
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
+#include <asm/ps3fb.h>
 
 #include "platform.h"
 
@@ -233,6 +234,9 @@
 
 static void ps3_hpte_clear(void)
 {
+	/* Make sure to clean up the frame buffer device first */
+	ps3fb_cleanup();
+
 	lv1_unmap_htab(htab_addr);
 }
 
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index e62505e..13d669a 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -24,6 +24,7 @@
 #include <linux/root_dev.h>
 #include <linux/console.h>
 #include <linux/kexec.h>
+#include <linux/bootmem.h>
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
@@ -80,6 +81,46 @@
 	for (;;) ;
 }
 
+
+static void prealloc(struct ps3_prealloc *p)
+{
+	if (!p->size)
+		return;
+
+	p->address = __alloc_bootmem(p->size, p->align, __pa(MAX_DMA_ADDRESS));
+	if (!p->address) {
+		printk(KERN_ERR "%s: Cannot allocate %s\n", __FUNCTION__,
+		       p->name);
+		return;
+	}
+
+	printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size,
+	       p->address);
+}
+
+#ifdef CONFIG_FB_PS3
+struct ps3_prealloc ps3fb_videomemory = {
+    .name = "ps3fb videomemory",
+    .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024,
+    .align = 1024*1024			/* the GPU requires 1 MiB alignment */
+};
+#define prealloc_ps3fb_videomemory()	prealloc(&ps3fb_videomemory)
+
+static int __init early_parse_ps3fb(char *p)
+{
+	if (!p)
+		return 1;
+
+	ps3fb_videomemory.size = _ALIGN_UP(memparse(p, &p),
+					   ps3fb_videomemory.align);
+	return 0;
+}
+early_param("ps3fb", early_parse_ps3fb);
+#else
+#define prealloc_ps3fb_videomemory()	do { } while (0)
+#endif
+
+
 static void __init ps3_setup_arch(void)
 {
 	union ps3_firmware_version v;
@@ -101,6 +142,7 @@
 	conswitchp = &dummy_con;
 #endif
 
+	prealloc_ps3fb_videomemory();
 	ppc_md.power_save = ps3_power_save;
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 9437f48..6cedbc0 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1078,7 +1078,7 @@
 	return single_open(file, proc_eeh_show, NULL);
 }
 
-static struct file_operations proc_eeh_operations = {
+static const struct file_operations proc_eeh_operations = {
 	.open      = proc_eeh_open,
 	.read      = seq_read,
 	.llseek    = seq_lseek,
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index 3ddc049..eae51ef 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -90,7 +90,7 @@
 	return rc;
 }
 
-static struct file_operations hcall_inst_seq_fops = {
+static const struct file_operations hcall_inst_seq_fops = {
 	.open = hcall_inst_seq_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 789a5e9..5aa97af 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -499,7 +499,7 @@
 	return rv ? rv : count;
 }
 
-static struct file_operations ofdt_fops = {
+static const struct file_operations ofdt_fops = {
 	.write = ofdt_write
 };
 
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index 8ca2612..77d0937 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -331,7 +331,7 @@
 	return 0;
 }
 
-struct file_operations proc_rtas_log_operations = {
+const struct file_operations proc_rtas_log_operations = {
 	.read =		rtas_log_read,
 	.poll =		rtas_log_poll,
 	.open =		rtas_log_open,
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 45368a5..8e1ef16 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -184,7 +184,7 @@
 	return 0;
 }
 
-struct file_operations scanlog_fops = {
+const struct file_operations scanlog_fops = {
 	.owner		= THIS_MODULE,
 	.read		= scanlog_read,
 	.write		= scanlog_write,
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index 684ed04..a956f28 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -1711,7 +1711,7 @@
 }
 
 
-static struct file_operations mixer_fops =
+static const struct file_operations mixer_fops =
 {
 	.owner =	THIS_MODULE,
 	.llseek =	sound_lseek,
@@ -2298,7 +2298,7 @@
 
 
 
-static struct file_operations sq_fops =
+static const struct file_operations sq_fops =
 {
 	.owner =	THIS_MODULE,
 	.llseek =	sound_lseek,
@@ -2433,7 +2433,7 @@
 }
 
 
-static struct file_operations state_fops =
+static const struct file_operations state_fops =
 {
 	.owner =	THIS_MODULE,
 	.llseek =	sound_lseek,
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 3c506af..c79704f 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -543,7 +543,7 @@
 	init_mm.brk = (unsigned long) klimit;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 	*cmdline_p = cmd_line;
 
 	parse_early_param();
diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
index 18dc6e8..b947c77 100644
--- a/arch/ppc/platforms/lopec.c
+++ b/arch/ppc/platforms/lopec.c
@@ -344,7 +344,7 @@
 		 if (bootargs != NULL) {
 			 strcpy(cmd_line, bootargs);
 			 /* again.. */
-			 strcpy(saved_command_line, cmd_line);
+			 strcpy(boot_command_line, cmd_line);
 		}
 	}
 #endif
diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
index 9778105..8a1788c 100644
--- a/arch/ppc/platforms/pplus.c
+++ b/arch/ppc/platforms/pplus.c
@@ -592,7 +592,7 @@
 		if (bootargs != NULL) {
 			strcpy(cmd_line, bootargs);
 			/* again.. */
-			strcpy(saved_command_line, cmd_line);
+			strcpy(boot_command_line, cmd_line);
 		}
 	}
 #endif
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 1cb75a1..f166299 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -634,7 +634,7 @@
 	/*
 	 * Find a way to push these informations to the cs4232 driver
 	 * Give it out with printk, when not in cmd_line?
-	 * Append it to  cmd_line and saved_command_line?
+	 * Append it to  cmd_line and boot_command_line?
 	 * Format is cs4232=io,irq,dma,dma2
 	 */
 }
@@ -897,7 +897,7 @@
 		 if (bootargs != NULL) {
 			 strcpy(cmd_line, bootargs);
 			 /* again.. */
-			 strcpy(saved_command_line, cmd_line);
+			 strcpy(boot_command_line, cmd_line);
 		}
 	}
 
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index a4fda7b..ba5d316 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -34,7 +34,7 @@
 	struct mutex lock;		/* lock to protect update process */
 };
 
-static struct file_operations hypfs_file_ops;
+static const struct file_operations hypfs_file_ops;
 static struct file_system_type hypfs_type;
 static struct super_operations hypfs_s_ops;
 
@@ -440,7 +440,7 @@
 	return dentry;
 }
 
-static struct file_operations hypfs_file_ops = {
+static const struct file_operations hypfs_file_ops = {
 	.open		= hypfs_open,
 	.release	= hypfs_release,
 	.read		= do_sync_read,
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index f4b62df..51653d8 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -167,7 +167,7 @@
 
 static int initialized;
 
-static struct file_operations debug_file_ops = {
+static const struct file_operations debug_file_ops = {
 	.owner   = THIS_MODULE,
 	.read    = debug_output,
 	.write   = debug_input,
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 0373981..50c5210 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -740,7 +740,7 @@
 #endif /* CONFIG_64BIT */
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
 
 	*cmdline_p = COMMAND_LINE;
 	*(*cmdline_p + COMMAND_LINE_SIZE - 1) = '\0';
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
index e625249..47a63c6 100644
--- a/arch/sh/boards/landisk/landisk_pwb.c
+++ b/arch/sh/boards/landisk/landisk_pwb.c
@@ -150,7 +150,7 @@
 	return IRQ_HANDLED;
 }
 
-static struct file_operations swdrv_fops = {
+static const struct file_operations swdrv_fops = {
 	.read = swdrv_read,	/* read */
 	.write = swdrv_write,	/* write */
 	.open = swdrv_open,	/* open */
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 225f9ea..d6b817a 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -75,7 +75,7 @@
 #define RAMDISK_PROMPT_FLAG		0x8000
 #define RAMDISK_LOAD_FLAG		0x4000
 
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
 
 static struct resource code_resource = { .name = "Kernel code", };
 static struct resource data_resource = { .name = "Kernel data", };
@@ -90,8 +90,8 @@
 	int len = 0;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
 	memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
 	memory_end = memory_start + __MEMORY_SIZE;
diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
index e0122bd..909dcfa 100644
--- a/arch/sh/mm/cache-debugfs.c
+++ b/arch/sh/mm/cache-debugfs.c
@@ -114,7 +114,7 @@
 	return single_open(file, cache_seq_show, inode->i_private);
 }
 
-static struct file_operations cache_debugfs_fops = {
+static const struct file_operations cache_debugfs_fops = {
 	.owner		= THIS_MODULE,
 	.open		= cache_debugfs_open,
 	.read		= seq_read,
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index b60ad83..d0d45e2 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -378,7 +378,7 @@
 	return single_open(file, pmb_seq_show, NULL);
 }
 
-static struct file_operations pmb_debugfs_fops = {
+static const struct file_operations pmb_debugfs_fops = {
 	.owner		= THIS_MODULE,
 	.open		= pmb_debugfs_open,
 	.read		= seq_read,
diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c
index 60402ee..0104e44 100644
--- a/arch/sh/oprofile/op_model_sh7750.c
+++ b/arch/sh/oprofile/op_model_sh7750.c
@@ -187,7 +187,7 @@
 	return count;
 }
 
-static struct file_operations count_fops = {
+static const struct file_operations count_fops = {
 	.read		= sh7750_read_count,
 	.write		= sh7750_write_count,
 };
diff --git a/arch/sh64/kernel/setup.c b/arch/sh64/kernel/setup.c
index b9e7d54..53e9d20 100644
--- a/arch/sh64/kernel/setup.c
+++ b/arch/sh64/kernel/setup.c
@@ -83,7 +83,7 @@
 #define RAMDISK_PROMPT_FLAG		0x8000
 #define RAMDISK_LOAD_FLAG		0x4000
 
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
+static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
 unsigned long long memory_start = CONFIG_MEMORY_START;
 unsigned long long memory_end = CONFIG_MEMORY_START + (CONFIG_MEMORY_SIZE_IN_MB * 1024 * 1024);
 
@@ -95,8 +95,8 @@
 	int len = 0;
 
 	/* Save unparsed command line copy for /proc/cmdline */
-	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
 	for (;;) {
 	  /*
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c
index 406dd94..d06a405 100644
--- a/arch/sparc/kernel/apc.c
+++ b/arch/sparc/kernel/apc.c
@@ -127,7 +127,7 @@
 	return 0;
 }
 
-static struct file_operations apc_fops = {
+static const struct file_operations apc_fops = {
 	.ioctl =	apc_ioctl,
 	.open =		apc_open,
 	.release =	apc_release,
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 383526a..eccd8e8 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -246,7 +246,7 @@
 
 	/* Initialize PROM console and command line. */
 	*cmdline_p = prom_getbootargs();
-	strcpy(saved_command_line, *cmdline_p);
+	strcpy(boot_command_line, *cmdline_p);
 
 	/* Set sparc_cpu_model */
 	sparc_cpu_model = sun_unknown;
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index d8e008a..bba1b0e 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -229,7 +229,7 @@
 EXPORT_SYMBOL(prom_getproperty);
 EXPORT_SYMBOL(prom_node_has_property);
 EXPORT_SYMBOL(prom_setprop);
-EXPORT_SYMBOL(saved_command_line);
+EXPORT_SYMBOL(boot_command_line);
 EXPORT_SYMBOL(prom_apply_obio_ranges);
 EXPORT_SYMBOL(prom_feval);
 EXPORT_SYMBOL(prom_getbool);
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index 0bf8c16..da6606f 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -859,14 +859,16 @@
 	return ret;
 }
 
-extern int kill_pg(int, int, int);
 asmlinkage int sunos_killpg(int pgrp, int sig)
 {
 	int ret;
 
-	lock_kernel();
-	ret = kill_pg(pgrp, sig, 0);
-	unlock_kernel();
+	rcu_read_lock();
+	ret = -EINVAL;
+	if (pgrp > 0)
+		ret = kill_pgrp(find_pid(pgrp), sig, 0);
+	rcu_read_unlock();
+
 	return ret;
 }
 
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index bf033b3..4510283 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -315,7 +315,7 @@
 {
 	/* Initialize PROM console and command line. */
 	*cmdline_p = prom_getbootargs();
-	strcpy(saved_command_line, *cmdline_p);
+	strcpy(boot_command_line, *cmdline_p);
 
 	if (tlb_type == hypervisor)
 		printk("ARCH: SUN4V\n");
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index beffc82..f7d78e0 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -253,7 +253,7 @@
 EXPORT_SYMBOL(prom_getproperty);
 EXPORT_SYMBOL(prom_node_has_property);
 EXPORT_SYMBOL(prom_setprop);
-EXPORT_SYMBOL(saved_command_line);
+EXPORT_SYMBOL(boot_command_line);
 EXPORT_SYMBOL(prom_finddevice);
 EXPORT_SYMBOL(prom_feval);
 EXPORT_SYMBOL(prom_getbool);
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 2ebc2c0..4cff95b 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -824,10 +824,17 @@
 	return ret;
 }
 
-extern int kill_pg(int, int, int);
 asmlinkage int sunos_killpg(int pgrp, int sig)
 {
-	return kill_pg(pgrp, sig, 0);
+	int ret;
+
+	rcu_read_lock();
+	ret = -EINVAL;
+	if (pgrp > 0)
+		ret = kill_pgrp(find_pid(pgrp), sig, 0);
+	rcu_read_unlock();
+
+	return ret;
 }
 
 asmlinkage int sunos_audit(void)
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 061e1b1..f84da4f 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -1327,7 +1327,7 @@
 }
 
 
-static struct file_operations mini_rtc_fops = {
+static const struct file_operations mini_rtc_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= mini_rtc_ioctl,
 	.open		= mini_rtc_open,
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index 89a4757..c286444 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -163,7 +163,7 @@
 	return mask;
 }
 	
-static struct file_operations socksys_fops = {
+static const struct file_operations socksys_fops = {
 	.open =		socksys_open,
 	.release =	socksys_release,
 };
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index 73c5caa..5560168 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -145,7 +145,7 @@
 	}
 }
 
-static struct file_operations harddog_fops = {
+static const struct file_operations harddog_fops = {
 	.owner		= THIS_MODULE,
 	.write		= harddog_write,
 	.ioctl		= harddog_ioctl,
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 0e1e9a2..01d4ab6 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -774,7 +774,7 @@
 		line = tty->driver_data;
 		chan_window_size(&line->chan_list, &tty->winsize.ws_row,
 				 &tty->winsize.ws_col);
-		kill_pg(tty->pgrp, SIGWINCH, 1);
+		kill_pgrp(tty->pgrp, SIGWINCH, 1);
 	}
  out:
 	if(winch->fd != -1)
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index 06625fe..023575f 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -38,8 +38,6 @@
 
 extern char host_info[];
 
-extern char saved_command_line[];
-
 extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
 extern unsigned long _unprotected_end;
 extern unsigned long brk_start;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 84e57f6..89c6dba 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -43,9 +43,9 @@
 #define DEFAULT_COMMAND_LINE "root=98:0"
 
 /* Changed in linux_main and setup_arch, which run before SMP is started */
-static char command_line[COMMAND_LINE_SIZE] = { 0 };
+static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };
 
-static void add_arg(char *arg)
+static void __init add_arg(char *arg)
 {
 	if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
 		printf("add_arg: Too many command line arguments!\n");
@@ -330,7 +330,7 @@
 
 extern char __binary_start;
 
-int linux_main(int argc, char **argv)
+int __init linux_main(int argc, char **argv)
 {
 	unsigned long avail, diff;
 	unsigned long virtmem_size, max_physmem;
@@ -481,7 +481,7 @@
 	atomic_notifier_chain_register(&panic_notifier_list,
 			&panic_exit_notifier);
 	paging_init();
-        strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
  	*cmdline_p = command_line;
 	setup_hostinfo();
 }
diff --git a/arch/v850/kernel/rte_cb_leds.c b/arch/v850/kernel/rte_cb_leds.c
index 996bd4f..aa47ab1 100644
--- a/arch/v850/kernel/rte_cb_leds.c
+++ b/arch/v850/kernel/rte_cb_leds.c
@@ -117,7 +117,7 @@
 	return 0;
 }
 
-static struct file_operations leds_fops = {
+static const struct file_operations leds_fops = {
 	.read		= leds_dev_read,
 	.write		= leds_dev_write,
 	.llseek		= leds_dev_lseek
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index 1bf672a..a914f24 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -42,7 +42,7 @@
 extern char _root_fs_image_end __attribute__ ((__weak__));
 
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 
 /* Memory not used by the kernel.  */
 static unsigned long total_ram_pages;
@@ -64,8 +64,8 @@
 {
 	/* Keep a copy of command line */
 	*cmdline = command_line;
-	memcpy (saved_command_line, command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
+	memcpy (boot_command_line, command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
 
 	console_verbose ();
 
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index cc230b9..5f197b0 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -34,8 +34,6 @@
 #define OLD_CL_BASE_ADDR        0x90000
 #define OLD_CL_OFFSET           0x90022
 
-extern char saved_command_line[];
-
 static void __init copy_bootdata(char *real_mode_data)
 {
 	int new_data;
@@ -50,7 +48,7 @@
 		new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
 	}
 	command_line = (char *) ((u64)(new_data));
-	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 }
 
 void __init x86_64_start_kernel(char * real_mode_data)
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index ac08503..bdb54a2 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -516,7 +516,7 @@
 	} 
 }
 
-static struct file_operations mce_chrdev_ops = {
+static const struct file_operations mce_chrdev_ops = {
 	.read = mce_read,
 	.ioctl = mce_ioctl,
 };
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index af425a8..6047724 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -100,7 +100,7 @@
 
 extern int root_mountflags;
 
-char command_line[COMMAND_LINE_SIZE];
+char __initdata command_line[COMMAND_LINE_SIZE];
 
 struct resource standard_io_resources[] = {
 	{ .name = "dma1", .start = 0x00, .end = 0x1f,
@@ -343,7 +343,7 @@
 
 void __init setup_arch(char **cmdline_p)
 {
-	printk(KERN_INFO "Command line: %s\n", saved_command_line);
+	printk(KERN_INFO "Command line: %s\n", boot_command_line);
 
  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
  	screen_info = SCREEN_INFO;
@@ -373,7 +373,7 @@
 
 	early_identify_cpu(&boot_cpu_data);
 
-	strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 
 	parse_early_param();
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index b6374c0..1ecf671 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -78,7 +78,7 @@
 
 /* Command line specified as configuration option. */
 
-static char command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
 
 #ifdef CONFIG_CMDLINE_BOOL
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
@@ -253,8 +253,8 @@
 	extern int mem_reserve(unsigned long, unsigned long, int);
 	extern void bootmem_init(void);
 
-	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	*cmdline_p = command_line;
 
 	/* Reserve some memory regions */
diff --git a/block/blktrace.c b/block/blktrace.c
index d36b32e..3f0e7c3 100644
--- a/block/blktrace.c
+++ b/block/blktrace.c
@@ -264,7 +264,7 @@
 	return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
 }
 
-static struct file_operations blk_dropped_fops = {
+static const struct file_operations blk_dropped_fops = {
 	.owner =	THIS_MODULE,
 	.open =		blk_dropped_open,
 	.read =		blk_dropped_read,
diff --git a/block/genhd.c b/block/genhd.c
index 457fdac..36bd3e1 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -61,6 +61,14 @@
 	/* temporary */
 	if (major == 0) {
 		for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) {
+			/*
+			 * Disallow the LANANA-assigned LOCAL/EXPERIMENTAL
+			 * majors
+			 */
+			if ((60 <= index && index <= 63) ||
+					(120 <= index && index <= 127) ||
+					(240 <= index && index <= 254))
+				continue;
 			if (major_names[index] == NULL)
 				break;
 		}
diff --git a/crypto/proc.c b/crypto/proc.c
index dabce06..102c751 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -101,7 +101,7 @@
 	return seq_open(file, &crypto_seq_ops);
 }
         
-static struct file_operations proc_crypto_ops = {
+static const struct file_operations proc_crypto_ops = {
 	.open		= crypto_info_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
index 9e584a7..157d8b7 100644
--- a/drivers/acorn/char/i2c.c
+++ b/drivers/acorn/char/i2c.c
@@ -238,7 +238,7 @@
 	return -EINVAL;
 }
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.ioctl	= rtc_ioctl,
 };
 
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 7b2fa3d..92bf868 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -7024,7 +7024,7 @@
   return -EINVAL;
 }
 
-static struct file_operations DAC960_gam_fops = {
+static const struct file_operations DAC960_gam_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= DAC960_gam_ioctl
 };
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index e04be94..e2e0432 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -269,7 +269,7 @@
 
 static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
 
-static struct file_operations slm_fops = {
+static const struct file_operations slm_fops = {
 	.owner =	THIS_MODULE,
 	.read =		slm_read,
 	.write =	slm_write,
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index e22b4c9..39e563e 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -233,7 +233,7 @@
 	}
 }
 
-static struct file_operations aoe_fops = {
+static const struct file_operations aoe_fops = {
 	.write = aoechr_write,
 	.read = aoechr_read,
 	.open = aoechr_open,
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 9970aed..d89e7d3 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -227,7 +227,7 @@
 
 /* kernel glue structures */
 
-static struct file_operations pg_fops = {
+static const struct file_operations pg_fops = {
 	.owner = THIS_MODULE,
 	.read = pg_read,
 	.write = pg_write,
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index c902b25..9f4e67e 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -232,7 +232,7 @@
 
 /* kernel glue structures */
 
-static struct file_operations pt_fops = {
+static const struct file_operations pt_fops = {
 	.owner = THIS_MODULE,
 	.read = pt_read,
 	.write = pt_write,
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index c0e8949..93fb6ed 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -435,7 +435,7 @@
 	return single_open(file, pkt_debugfs_seq_show, inode->i_private);
 }
 
-static struct file_operations debug_fops = {
+static const struct file_operations debug_fops = {
 	.open		= pkt_debugfs_fops_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -2725,7 +2725,7 @@
 	return single_open(file, pkt_seq_show, PDE(inode)->data);
 }
 
-static struct file_operations pkt_proc_fops = {
+static const struct file_operations pkt_proc_fops = {
 	.open	= pkt_seq_open,
 	.read	= seq_read,
 	.llseek	= seq_lseek,
@@ -3052,7 +3052,7 @@
 }
 
 
-static struct file_operations pkt_ctl_fops = {
+static const struct file_operations pkt_ctl_fops = {
 	.ioctl	 = pkt_ctl_ioctl,
 	.owner	 = THIS_MODULE,
 };
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index a278d98..b71a5cc 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -332,7 +332,7 @@
 	return 0;
 }
 
-static struct file_operations vhci_fops = {
+static const struct file_operations vhci_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= vhci_llseek,
 	.read		= vhci_read,
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 93fbf84..dc13eba 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -176,7 +176,7 @@
 	return single_open(file, proc_viocd_show, NULL);
 }
 
-static struct file_operations proc_viocd_operations = {
+static const struct file_operations proc_viocd_operations = {
 	.open		= proc_viocd_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index 9f8082f..7f60a18 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -187,7 +187,7 @@
 	return len;
 }
 
-static struct file_operations briq_panel_fops = {
+static const struct file_operations briq_panel_fops = {
 	.owner		= THIS_MODULE,
 	.read		= briq_panel_read,
 	.write		= briq_panel_write,
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 363beb1..54df355 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -829,17 +829,18 @@
 static unsigned short cy_isa_nboard;
 static unsigned short cy_nboard;
 #ifdef CONFIG_PCI
-static unsigned short cy_pci_dev_id[] = {
-	PCI_DEVICE_ID_CYCLOM_Y_Lo,	/* PCI < 1Mb */
-	PCI_DEVICE_ID_CYCLOM_Y_Hi,	/* PCI > 1Mb */
-	PCI_DEVICE_ID_CYCLOM_4Y_Lo,	/* 4Y PCI < 1Mb */
-	PCI_DEVICE_ID_CYCLOM_4Y_Hi,	/* 4Y PCI > 1Mb */
-	PCI_DEVICE_ID_CYCLOM_8Y_Lo,	/* 8Y PCI < 1Mb */
-	PCI_DEVICE_ID_CYCLOM_8Y_Hi,	/* 8Y PCI > 1Mb */
-	PCI_DEVICE_ID_CYCLOM_Z_Lo,	/* Z PCI < 1Mb */
-	PCI_DEVICE_ID_CYCLOM_Z_Hi,	/* Z PCI > 1Mb */
-	0			/* end of table */
+static struct pci_device_id cy_pci_dev_id[] __devinitdata = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },	/* PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },	/* PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },	/* 4Y PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },	/* 4Y PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },	/* 8Y PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },	/* 8Y PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },	/* Z PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },	/* Z PCI > 1Mb */
+	{ }			/* end of table */
 };
+MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
 #endif
 
 static void cy_start(struct tty_struct *);
@@ -4758,7 +4759,7 @@
 
 	for (i = 0; i < NR_CARDS; i++) {
 		/* look for a Cyclades card by vendor and device id */
-		while ((device_id = cy_pci_dev_id[dev_index]) != 0) {
+		while ((device_id = cy_pci_dev_id[dev_index].device) != 0) {
 			if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
 						   device_id, pdev)) == NULL) {
 				dev_index++;	/* try next device id */
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index a70af0d..f5b9b24 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -371,7 +371,7 @@
 EXPORT_SYMBOL(drm_exit);
 
 /** File operations structure */
-static struct file_operations drm_stub_fops = {
+static const struct file_operations drm_stub_fops = {
 	.owner = THIS_MODULE,
 	.open = drm_stub_open
 };
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 60cb4e4..603d17f 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -112,7 +112,7 @@
 	return 0;
 }
 
-static struct file_operations i810_buffer_fops = {
+static const struct file_operations i810_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
 	.ioctl = drm_ioctl,
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 9522445..3314a9f 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -114,7 +114,7 @@
 	return 0;
 }
 
-static struct file_operations i830_buffer_fops = {
+static const struct file_operations i830_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
 	.ioctl = drm_ioctl,
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index 2054d57..2881a06 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -376,10 +376,8 @@
 			blitq->cur = cur;
 			blitq->num_outstanding--;
 			blitq->end = jiffies + DRM_HZ;
-			if (!timer_pending(&blitq->poll_timer)) {
-				blitq->poll_timer.expires = jiffies+1;
-				add_timer(&blitq->poll_timer);
-			}
+			if (!timer_pending(&blitq->poll_timer))
+				mod_timer(&blitq->poll_timer, jiffies + 1);
 		} else {
 			if (timer_pending(&blitq->poll_timer)) {
 				del_timer(&blitq->poll_timer);
@@ -478,8 +476,7 @@
 	via_dmablit_handler(dev, engine, 0);
 	
 	if (!timer_pending(&blitq->poll_timer)) {
-		blitq->poll_timer.expires = jiffies+1;
-		add_timer(&blitq->poll_timer);
+		mod_timer(&blitq->poll_timer, jiffies + 1);
 
 	       /*
 		* Rerun handler to delete timer if engines are off, and
@@ -574,9 +571,8 @@
 		}
 		DRM_INIT_WAITQUEUE(&blitq->busy_queue);
 		INIT_WORK(&blitq->wq, via_dmablit_workqueue);
-		init_timer(&blitq->poll_timer);
-		blitq->poll_timer.function = &via_dmablit_timer;
-		blitq->poll_timer.data = (unsigned long) blitq;
+		setup_timer(&blitq->poll_timer, via_dmablit_timer,
+				(unsigned long)blitq);
 	}	
 }
 
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c
index bcdb107..fada6dd 100644
--- a/drivers/char/ds1302.c
+++ b/drivers/char/ds1302.c
@@ -120,7 +120,6 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	local_irq_disable();
 
 	rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
 	rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
@@ -219,7 +218,6 @@
 			BIN_TO_BCD(yrs);
 
 			local_irq_save(flags);
-			local_irq_disable();
 			CMOS_WRITE(yrs, RTC_YEAR);
 			CMOS_WRITE(mon, RTC_MONTH);
 			CMOS_WRITE(day, RTC_DAY_OF_MONTH);
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index d4005e9..d8dbdb9 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -72,6 +72,7 @@
 #define TRACE_RET ((void) 0)
 #endif				/* TRACING */
 
+static void dtlk_timer_tick(unsigned long data);
 
 static int dtlk_major;
 static int dtlk_port_lpc;
@@ -81,7 +82,7 @@
 static unsigned int dtlk_portlist[] =
 {0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0};
 static wait_queue_head_t dtlk_process_list;
-static struct timer_list dtlk_timer;
+static DEFINE_TIMER(dtlk_timer, dtlk_timer_tick, 0, 0);
 
 /* prototypes for file_operations struct */
 static ssize_t dtlk_read(struct file *, char __user *,
@@ -117,7 +118,6 @@
 /*
    static void dtlk_handle_error(char, char, unsigned int);
  */
-static void dtlk_timer_tick(unsigned long data);
 
 static ssize_t dtlk_read(struct file *file, char __user *buf,
 			 size_t count, loff_t * ppos)
@@ -318,7 +318,7 @@
 	}
 	TRACE_RET;
 	
-	del_timer(&dtlk_timer);
+	del_timer_sync(&dtlk_timer);
 
 	return 0;
 }
@@ -336,8 +336,6 @@
 	if (dtlk_dev_probe() == 0)
 		printk(", MAJOR %d\n", dtlk_major);
 
-	init_timer(&dtlk_timer);
-	dtlk_timer.function = dtlk_timer_tick;
 	init_waitqueue_head(&dtlk_process_list);
 
 	return 0;
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 43ff598..2398e86 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -117,7 +117,7 @@
 	return 0;
 }
 
-struct file_operations nvram_fops = {
+const struct file_operations nvram_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= nvram_llseek,
 	.read		= read_nvram,
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index f22e78e..cc1046e 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -96,49 +96,49 @@
  */
 static const struct pci_device_id pci_tbl[] = {
 /* AA
-	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */
+	{ PCI_DEVICE(0x8086, 0x2418) }, */
+	{ PCI_DEVICE(0x8086, 0x2410) }, /* AA */
 /* AB
-	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */
+	{ PCI_DEVICE(0x8086, 0x2428) }, */
+	{ PCI_DEVICE(0x8086, 0x2420) }, /* AB */
 /* ??
-	{ 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
+	{ PCI_DEVICE(0x8086, 0x2430) }, */
 /* BAM, CAM, DBM, FBM, GxM
-	{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */
-	{ 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */
-	{ 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */
-	{ 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */
-	{ 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */
-	{ 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */
+	{ PCI_DEVICE(0x8086, 0x2448) }, */
+	{ PCI_DEVICE(0x8086, 0x244c) }, /* BAM */
+	{ PCI_DEVICE(0x8086, 0x248c) }, /* CAM */
+	{ PCI_DEVICE(0x8086, 0x24cc) }, /* DBM */
+	{ PCI_DEVICE(0x8086, 0x2641) }, /* FBM */
+	{ PCI_DEVICE(0x8086, 0x27b9) }, /* GxM */
+	{ PCI_DEVICE(0x8086, 0x27bd) }, /* GxM DH */
 /* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx
-	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */
-	{ 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */
-	{ 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */
-	{ 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */
-	{ 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */
-	{ 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */
-	{ 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */
-	{ 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */
+	{ PCI_DEVICE(0x8086, 0x244e) }, */
+	{ PCI_DEVICE(0x8086, 0x2440) }, /* BA */
+	{ PCI_DEVICE(0x8086, 0x2480) }, /* CA */
+	{ PCI_DEVICE(0x8086, 0x24c0) }, /* DB */
+	{ PCI_DEVICE(0x8086, 0x24d0) }, /* Ex */
+	{ PCI_DEVICE(0x8086, 0x25a1) }, /* 6300 */
+	{ PCI_DEVICE(0x8086, 0x2640) }, /* Fx */
+	{ PCI_DEVICE(0x8086, 0x2670) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2671) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2672) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2673) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2674) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2675) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2676) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2677) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2678) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x2679) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267a) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267b) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267c) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267d) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267e) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x267f) }, /* 631x/632x */
+	{ PCI_DEVICE(0x8086, 0x27b8) }, /* Gx */
 /* E
-	{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */
-	{ 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E  */
+	{ PCI_DEVICE(0x8086, 0x245e) }, */
+	{ PCI_DEVICE(0x8086, 0x2450) }, /* E  */
 	{ 0, },	/* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, pci_tbl);
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index 88b9d33..f86fa0c 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -80,7 +80,7 @@
 // Not a documented part of the library routines (careful...) but the Diagnostic
 // i2diag.c finds them useful to help the throughput in certain limited
 // single-threaded operations.
-static void iiSendPendingMail(i2eBordStrPtr);
+static inline void iiSendPendingMail(i2eBordStrPtr);
 static void serviceOutgoingFifo(i2eBordStrPtr);
 
 // Functions defined in ip2.c as part of interrupt handling
@@ -150,6 +150,13 @@
 			  == (CHANNEL_MAGIC | CHANNEL_SUPPORT));
 }
 
+static void iiSendPendingMail_t(unsigned long data)
+{
+	i2eBordStrPtr pB = (i2eBordStrPtr)data;
+
+	iiSendPendingMail(pB);
+}
+
 //******************************************************************************
 // Function:   iiSendPendingMail(pB)
 // Parameters: Pointer to a board structure
@@ -184,12 +191,9 @@
 			/\/\|=mhw=|\/\/				*/
 
 			if( ++pB->SendPendingRetry < 16 ) {
-
-				init_timer( &(pB->SendPendingTimer) );
-				pB->SendPendingTimer.expires  = jiffies + 1;
-				pB->SendPendingTimer.function = (void*)(unsigned long)iiSendPendingMail;
-				pB->SendPendingTimer.data     = (unsigned long)pB;
-				add_timer( &(pB->SendPendingTimer) );
+				setup_timer(&pB->SendPendingTimer,
+					iiSendPendingMail_t, (unsigned long)pB);
+				mod_timer(&pB->SendPendingTimer, jiffies + 1);
 			} else {
 				printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" );
 			}
@@ -1265,8 +1269,10 @@
 // soon as all the data is completely sent.
 //******************************************************************************
 static void
-i2DrainWakeup(i2ChanStrPtr pCh)
+i2DrainWakeup(unsigned long d)
 {
+	i2ChanStrPtr pCh = (i2ChanStrPtr)d;
+
 	ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );
 
 	pCh->BookmarkTimer.expires = 0;
@@ -1292,14 +1298,12 @@
 	}
 	if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) {
 		// One per customer (channel)
-		init_timer( &(pCh->BookmarkTimer) );
-		pCh->BookmarkTimer.expires  = jiffies + timeout;
-		pCh->BookmarkTimer.function = (void*)(unsigned long)i2DrainWakeup;
-		pCh->BookmarkTimer.data     = (unsigned long)pCh;
+		setup_timer(&pCh->BookmarkTimer, i2DrainWakeup,
+				(unsigned long)pCh);
 
 		ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );
 
-		add_timer( &(pCh->BookmarkTimer) );
+		mod_timer(&pCh->BookmarkTimer, jiffies + timeout);
 	}
 	
 	i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ );
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 7c70310..83c7258 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -1271,8 +1271,8 @@
 // code duplicated from n_tty (ldisc)
 static inline void  isig(int sig, struct tty_struct *tty, int flush)
 {
-	if (tty->pgrp > 0)
-		kill_pg(tty->pgrp, sig, 1);
+	if (tty->pgrp)
+		kill_pgrp(tty->pgrp, sig, 1);
 	if (flush || !L_NOFLSH(tty)) {
 		if ( tty->ldisc.flush_buffer )  
 			tty->ldisc.flush_buffer(tty);
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 0afb7ba..57f9115 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -46,7 +46,7 @@
 /*
  * file operations
  */
-struct file_operations mbcs_ops = {
+const struct file_operations mbcs_ops = {
 	.open = mbcs_open,
 	.llseek = mbcs_sram_llseek,
 	.read = mbcs_sram_read,
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 235e892..7ac3061 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -291,7 +291,7 @@
 	return mspec_mmap(file, vma, MSPEC_UNCACHED);
 }
 
-static struct file_operations fetchop_fops = {
+static const struct file_operations fetchop_fops = {
 	.owner = THIS_MODULE,
 	.mmap = fetchop_mmap
 };
@@ -302,7 +302,7 @@
 	.fops = &fetchop_fops
 };
 
-static struct file_operations cached_fops = {
+static const struct file_operations cached_fops = {
 	.owner = THIS_MODULE,
 	.mmap = cached_mmap
 };
@@ -313,7 +313,7 @@
 	.fops = &cached_fops
 };
 
-static struct file_operations uncached_fops = {
+static const struct file_operations uncached_fops = {
 	.owner = THIS_MODULE,
 	.mmap = uncached_mmap
 };
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index fab1b7d..65f2d3a 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1005,9 +1005,7 @@
 	tty->disc_data = pInfo;
 	tty->receive_room = 65536;
 
-	init_timer(&pInfo->tmr);
-	pInfo->tmr.data = (unsigned long)pInfo;
-	pInfo->tmr.function = on_timeout;
+	setup_timer(&pInfo->tmr, on_timeout, (unsigned long)pInfo);
 
 	return 0;
 }
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 2bdb014..6ac3ca4 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -579,8 +579,8 @@
  
 static inline void isig(int sig, struct tty_struct *tty, int flush)
 {
-	if (tty->pgrp > 0)
-		kill_pg(tty->pgrp, sig, 1);
+	if (tty->pgrp)
+		kill_pgrp(tty->pgrp, sig, 1);
 	if (flush || !L_NOFLSH(tty)) {
 		n_tty_flush_buffer(tty);
 		if (tty->driver->flush_buffer)
@@ -1184,13 +1184,13 @@
 	/* don't stop on /dev/console */
 	if (file->f_op->write != redirected_tty_write &&
 	    current->signal->tty == tty) {
-		if (tty->pgrp <= 0)
-			printk("read_chan: tty->pgrp <= 0!\n");
-		else if (process_group(current) != tty->pgrp) {
+		if (!tty->pgrp)
+			printk("read_chan: no tty->pgrp!\n");
+		else if (task_pgrp(current) != tty->pgrp) {
 			if (is_ignored(SIGTTIN) ||
-			    is_orphaned_pgrp(process_group(current)))
+			    is_current_pgrp_orphaned())
 				return -EIO;
-			kill_pg(process_group(current), SIGTTIN, 1);
+			kill_pgrp(task_pgrp(current), SIGTTIN, 1);
 			return -ERESTARTSYS;
 		}
 	}
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index 2d26497..2604246 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -23,8 +23,11 @@
 #define __NWBUTTON_C		/* Tell the header file who we are */
 #include "nwbutton.h"
 
+static void button_sequence_finished (unsigned long parameters);
+
 static int button_press_count;		/* The count of button presses */
-static struct timer_list button_timer;	/* Times for the end of a sequence */ 
+/* Times for the end of a sequence */
+static DEFINE_TIMER(button_timer, button_sequence_finished, 0, 0);
 static DECLARE_WAIT_QUEUE_HEAD(button_wait_queue); /* Used for blocking read */
 static char button_output_buffer[32];	/* Stores data to write out of device */
 static int bcount;			/* The number of bytes in the buffer */
@@ -146,14 +149,8 @@
 
 static irqreturn_t button_handler (int irq, void *dev_id)
 {
-	if (button_press_count) {
-		del_timer (&button_timer);
-	}
 	button_press_count++;
-	init_timer (&button_timer);
-	button_timer.function = button_sequence_finished;
-	button_timer.expires = (jiffies + bdelay);
-	add_timer (&button_timer);
+	mod_timer(&button_timer, jiffies + bdelay);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 211c93f..e91b43a 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -946,8 +946,7 @@
 
 return_with_timer:
 	DEBUGP(7, dev, "<- monitor_card (returns with timer)\n");
-	dev->timer.expires = jiffies + dev->mdelay;
-	add_timer(&dev->timer);
+	mod_timer(&dev->timer, jiffies + dev->mdelay);
 	clear_bit(LOCK_MONITOR, &dev->flags);
 }
 
@@ -1406,12 +1405,9 @@
 	DEBUGP(3, dev, "-> start_monitor\n");
 	if (!dev->monitor_running) {
 		DEBUGP(5, dev, "create, init and add timer\n");
-		init_timer(&dev->timer);
+		setup_timer(&dev->timer, monitor_card, (unsigned long)dev);
 		dev->monitor_running = 1;
-		dev->timer.expires = jiffies;
-		dev->timer.data = (unsigned long) dev;
-		dev->timer.function = monitor_card;
-		add_timer(&dev->timer);
+		mod_timer(&dev->timer, jiffies);
 	} else
 		DEBUGP(5, dev, "monitor already running\n");
 	DEBUGP(3, dev, "<- start_monitor\n");
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 9b1ff7e..0e82968 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -632,8 +632,7 @@
 	init_waitqueue_head(&dev->poll_wait);
 	init_waitqueue_head(&dev->read_wait);
 	init_waitqueue_head(&dev->write_wait);
-	init_timer(&dev->poll_timer);
-	dev->poll_timer.function = &cm4040_do_poll;
+	setup_timer(&dev->poll_timer, cm4040_do_poll, 0);
 
 	ret = reader_config(link, i);
 	if (ret)
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 4ab2c98..8d025e9 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1361,9 +1361,7 @@
 	
 	memset(&info->icount, 0, sizeof(info->icount));
 
-	init_timer(&info->tx_timer);
-	info->tx_timer.data = (unsigned long)info;
-	info->tx_timer.function = tx_timeout;
+	setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
 
 	/* Allocate and claim adapter resources */
 	retval = claim_resources(info);
@@ -1408,7 +1406,7 @@
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 
-	del_timer(&info->tx_timer);	
+	del_timer_sync(&info->tx_timer);
 
 	if (info->tx_buf) {
 		free_page((unsigned long) info->tx_buf);
@@ -3549,8 +3547,8 @@
 		} else {
 			info->tx_active = 1;
 			tx_ready(info);
-			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
-			add_timer(&info->tx_timer);	
+			mod_timer(&info->tx_timer, jiffies +
+					msecs_to_jiffies(5000));
 		}
 	}
 
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 13d0b13..b9dc7aa 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1117,14 +1117,14 @@
 	}
 }
 
-struct file_operations random_fops = {
+const struct file_operations random_fops = {
 	.read  = random_read,
 	.write = random_write,
 	.poll  = random_poll,
 	.ioctl = random_ioctl,
 };
 
-struct file_operations urandom_fops = {
+const struct file_operations urandom_fops = {
 	.read  = urandom_read,
 	.write = random_write,
 	.ioctl = random_ioctl,
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index e79b2ed..85c1618 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -418,8 +418,7 @@
 	func_enter();
 
 	rio_interrupt(0, &p->RIOHosts[data]);
-	p->RIOHosts[data].timer.expires = jiffies + rio_poll;
-	add_timer(&p->RIOHosts[data].timer);
+	mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll);
 
 	func_exit();
 }
@@ -1154,13 +1153,10 @@
 		/* Init the timer "always" to make sure that it can safely be
 		   deleted when we unload... */
 
-		init_timer(&hp->timer);
+		setup_timer(&hp->timer, rio_pollfunc, i);
 		if (!hp->Ivec) {
 			rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll);
-			hp->timer.data = i;
-			hp->timer.function = rio_pollfunc;
-			hp->timer.expires = jiffies + rio_poll;
-			add_timer(&hp->timer);
+			mod_timer(&hp->timer, jiffies + rio_poll);
 		}
 	}
 
@@ -1191,7 +1187,7 @@
 			rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
 		}
 		/* It is safe/allowed to del_timer a non-active timer */
-		del_timer(&hp->timer);
+		del_timer_sync(&hp->timer);
 		if (hp->Caddr)
 			iounmap(hp->Caddr);
 		if (hp->Type == RIO_PCI)
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 106f225..76357c8 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -106,6 +106,8 @@
 
 /****** RocketPort Local Variables ******/
 
+static void rp_do_poll(unsigned long dummy);
+
 static struct tty_driver *rocket_driver;
 
 static struct rocket_version driver_version = {	
@@ -116,7 +118,7 @@
 static unsigned int xmit_flags[NUM_BOARDS];	       /*  Bit significant, indicates port had data to transmit. */
 						       /*  eg.  Bit 0 indicates port 0 has xmit data, ...        */
 static atomic_t rp_num_ports_open;	               /*  Number of serial ports open                           */
-static struct timer_list rocket_timer;
+static DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0);
 
 static unsigned long board1;	                       /* ISA addresses, retrieved from rocketport.conf          */
 static unsigned long board2;
@@ -2368,12 +2370,6 @@
 		return -ENOMEM;
 
 	/*
-	 * Set up the timer channel.
-	 */
-	init_timer(&rocket_timer);
-	rocket_timer.function = rp_do_poll;
-
-	/*
 	 * Initialize the array of pointers to our own internal state
 	 * structures.
 	 */
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 664f36c..b6d3072 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -135,7 +135,9 @@
 static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
 
 #ifdef RTC_IRQ
-static struct timer_list rtc_irq_timer;
+static void rtc_dropped_irq(unsigned long data);
+
+static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0);
 #endif
 
 static ssize_t rtc_read(struct file *file, char __user *buf,
@@ -150,8 +152,6 @@
 
 static void get_rtc_alm_time (struct rtc_time *alm_tm);
 #ifdef RTC_IRQ
-static void rtc_dropped_irq(unsigned long data);
-
 static void set_rtc_irq_bit_locked(unsigned char bit);
 static void mask_rtc_irq_bit_locked(unsigned char bit);
 
@@ -454,8 +454,8 @@
 
 		spin_lock_irqsave (&rtc_lock, flags);
 		if (!(rtc_status & RTC_TIMER_ON)) {
-			rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
-			add_timer(&rtc_irq_timer);
+			mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq +
+					2*HZ/100);
 			rtc_status |= RTC_TIMER_ON;
 		}
 		set_rtc_irq_bit_locked(RTC_PIE);
@@ -1084,8 +1084,6 @@
 	if (rtc_has_irq == 0)
 		goto no_irq2;
 
-	init_timer(&rtc_irq_timer);
-	rtc_irq_timer.function = rtc_dropped_irq;
 	spin_lock_irq(&rtc_lock);
 	rtc_freq = 1024;
 	if (!hpet_set_periodic_freq(rtc_freq)) {
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 92043c8..baf7234 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -459,10 +459,9 @@
 	if (irq) {
 		printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
 		sx_interrupt (((struct specialix_board *)data)->irq,
-		              (void*)data, NULL);
+				(void*)data);
 	}
-	missed_irq_timer.expires = jiffies + sx_poll;
-	add_timer (&missed_irq_timer);
+	mod_timer(&missed_irq_timer, jiffies + sx_poll);
 }
 #endif
 
@@ -597,11 +596,8 @@
 	dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
 
 #ifdef SPECIALIX_TIMER
-	init_timer (&missed_irq_timer);
-	missed_irq_timer.function = missed_irq;
-	missed_irq_timer.data = (unsigned long) bp;
-	missed_irq_timer.expires = jiffies + sx_poll;
-	add_timer (&missed_irq_timer);
+	setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp);
+	mod_timer(&missed_irq_timer, jiffies + sx_poll);
 #endif
 
 	printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
@@ -2559,7 +2555,7 @@
 		if (sx_board[i].flags & SX_BOARD_PRESENT)
 			sx_release_io_range(&sx_board[i]);
 #ifdef SPECIALIX_TIMER
-	del_timer (&missed_irq_timer);
+	del_timer_sync(&missed_irq_timer);
 #endif
 
 	func_exit();
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index bf76db1..ce4db6f 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1798,9 +1798,7 @@
 	
 	memset(&info->icount, 0, sizeof(info->icount));
 
-	init_timer(&info->tx_timer);
-	info->tx_timer.data = (unsigned long)info;
-	info->tx_timer.function = mgsl_tx_timeout;
+	setup_timer(&info->tx_timer, mgsl_tx_timeout, (unsigned long)info);
 	
 	/* Allocate and claim adapter resources */
 	retval = mgsl_claim_resources(info);
@@ -1851,7 +1849,7 @@
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 
-	del_timer(&info->tx_timer);	
+	del_timer_sync(&info->tx_timer);
 
 	if (info->xmit_buf) {
 		free_page((unsigned long) info->xmit_buf);
@@ -5710,8 +5708,8 @@
 			
 			usc_TCmd( info, TCmd_SendFrame );
 			
-			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
-			add_timer(&info->tx_timer);	
+			mod_timer(&info->tx_timer, jiffies +
+					msecs_to_jiffies(5000));
 		}
 		info->tx_active = 1;
 	}
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 54af763..0a367cd 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1825,8 +1825,7 @@
 		if (i < count) {
 			/* receive buffer not completed */
 			info->rbuf_index += i;
-			info->rx_timer.expires = jiffies + 1;
-			add_timer(&info->rx_timer);
+			mod_timer(&info->rx_timer, jiffies + 1);
 			break;
 		}
 
@@ -3340,13 +3339,8 @@
 		info->adapter_num = adapter_num;
 		info->port_num = port_num;
 
-		init_timer(&info->tx_timer);
-		info->tx_timer.data = (unsigned long)info;
-		info->tx_timer.function = tx_timeout;
-
-		init_timer(&info->rx_timer);
-		info->rx_timer.data = (unsigned long)info;
-		info->rx_timer.function = rx_timeout;
+		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
+		setup_timer(&info->rx_timer, rx_timeout, (unsigned long)info);
 
 		/* Copy configuration info to device instance data */
 		info->pdev = pdev;
@@ -3794,10 +3788,9 @@
 				}
 			}
 
-			if (info->params.mode == MGSL_MODE_HDLC) {
-				info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
-				add_timer(&info->tx_timer);
-			}
+			if (info->params.mode == MGSL_MODE_HDLC)
+				mod_timer(&info->tx_timer, jiffies +
+						msecs_to_jiffies(5000));
 		} else {
 			tdma_reset(info);
 			/* set 1st descriptor address */
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ebde4e5..ef93d05 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -2744,8 +2744,7 @@
 
 	change_params(info);
 
-	info->status_timer.expires = jiffies + msecs_to_jiffies(10);
-	add_timer(&info->status_timer);
+	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
 
 	if (info->tty)
 		clear_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -3841,13 +3840,9 @@
 		info->bus_type = MGSL_BUS_TYPE_PCI;
 		info->irq_flags = IRQF_SHARED;
 
-		init_timer(&info->tx_timer);
-		info->tx_timer.data = (unsigned long)info;
-		info->tx_timer.function = tx_timeout;
-
-		init_timer(&info->status_timer);
-		info->status_timer.data = (unsigned long)info;
-		info->status_timer.function = status_timeout;
+		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
+		setup_timer(&info->status_timer, status_timeout,
+				(unsigned long)info);
 
 		/* Store the PCI9050 misc control register value because a flaw
 		 * in the PCI9050 prevents LCR registers from being read if
@@ -4291,8 +4286,8 @@
 			write_reg(info, TXDMA + DIR, 0x40);		/* enable Tx DMA interrupts (EOM) */
 			write_reg(info, TXDMA + DSR, 0xf2);		/* clear Tx DMA IRQs, enable Tx DMA */
 	
-			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
-			add_timer(&info->tx_timer);
+			mod_timer(&info->tx_timer, jiffies +
+					msecs_to_jiffies(5000));
 		}
 		else {
 			tx_load_fifo(info);
@@ -5574,10 +5569,7 @@
 	if (status)
 		isr_io_pin(info,status);
 
-	info->status_timer.data = (unsigned long)info;
-	info->status_timer.function = status_timeout;
-	info->status_timer.expires = jiffies + msecs_to_jiffies(10);
-	add_timer(&info->status_timer);
+	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
 }
 
 
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 33e1f66..2f572b9 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1107,9 +1107,8 @@
 
 	INIT_WORK(&chip->work, timeout_work);
 
-	init_timer(&chip->user_read_timer);
-	chip->user_read_timer.function = user_reader_timeout;
-	chip->user_read_timer.data = (unsigned long) chip;
+	setup_timer(&chip->user_read_timer, user_reader_timeout,
+			(unsigned long)chip);
 
 	memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
 
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
index 7fca5f4..4eba32b 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_bios.c
@@ -441,7 +441,7 @@
 	return err;
 }
 
-struct file_operations tpm_ascii_bios_measurements_ops = {
+const struct file_operations tpm_ascii_bios_measurements_ops = {
 	.open = tpm_ascii_bios_measurements_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
@@ -474,7 +474,7 @@
 	return err;
 }
 
-struct file_operations tpm_binary_bios_measurements_ops = {
+const struct file_operations tpm_binary_bios_measurements_ops = {
 	.open = tpm_binary_bios_measurements_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 558ca92..65672c5 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -155,6 +155,8 @@
 	      unsigned int cmd, unsigned long arg);
 static int tty_fasync(int fd, struct file * filp, int on);
 static void release_tty(struct tty_struct *tty, int idx);
+static struct pid *__proc_set_tty(struct task_struct *tsk,
+				struct tty_struct *tty);
 
 /**
  *	alloc_tty_struct	-	allocate a tty object
@@ -1109,17 +1111,17 @@
 {
 	if (current->signal->tty != tty)
 		return 0;
-	if (tty->pgrp <= 0) {
-		printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n");
+	if (!tty->pgrp) {
+		printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
 		return 0;
 	}
-	if (process_group(current) == tty->pgrp)
+	if (task_pgrp(current) == tty->pgrp)
 		return 0;
 	if (is_ignored(SIGTTOU))
 		return 0;
-	if (is_orphaned_pgrp(process_group(current)))
+	if (is_current_pgrp_orphaned())
 		return -EIO;
-	(void) kill_pg(process_group(current), SIGTTOU, 1);
+	(void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
 	return -ERESTARTSYS;
 }
 
@@ -1354,8 +1356,8 @@
 	  tty_release is called */
 	
 	read_lock(&tasklist_lock);
-	if (tty->session > 0) {
-		do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+	if (tty->session) {
+		do_each_pid_task(tty->session, PIDTYPE_SID, p) {
 			spin_lock_irq(&p->sighand->siglock);
 			if (p->signal->tty == tty)
 				p->signal->tty = NULL;
@@ -1365,16 +1367,17 @@
 			}
 			__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
 			__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
-			if (tty->pgrp > 0)
-				p->signal->tty_old_pgrp = tty->pgrp;
+			put_pid(p->signal->tty_old_pgrp);  /* A noop */
+			if (tty->pgrp)
+				p->signal->tty_old_pgrp = get_pid(tty->pgrp);
 			spin_unlock_irq(&p->sighand->siglock);
-		} while_each_task_pid(tty->session, PIDTYPE_SID, p);
+		} while_each_pid_task(tty->session, PIDTYPE_SID, p);
 	}
 	read_unlock(&tasklist_lock);
 
 	tty->flags = 0;
-	tty->session = 0;
-	tty->pgrp = -1;
+	tty->session = NULL;
+	tty->pgrp = NULL;
 	tty->ctrl_status = 0;
 	/*
 	 *	If one of the devices matches a console pointer, we
@@ -1459,12 +1462,12 @@
 
 EXPORT_SYMBOL(tty_hung_up_p);
 
-static void session_clear_tty(pid_t session)
+static void session_clear_tty(struct pid *session)
 {
 	struct task_struct *p;
-	do_each_task_pid(session, PIDTYPE_SID, p) {
+	do_each_pid_task(session, PIDTYPE_SID, p) {
 		proc_clear_tty(p);
-	} while_each_task_pid(session, PIDTYPE_SID, p);
+	} while_each_pid_task(session, PIDTYPE_SID, p);
 }
 
 /**
@@ -1494,46 +1497,54 @@
 void disassociate_ctty(int on_exit)
 {
 	struct tty_struct *tty;
-	int tty_pgrp = -1;
-	int session;
+	struct pid *tty_pgrp = NULL;
 
 	lock_kernel();
 
 	mutex_lock(&tty_mutex);
 	tty = get_current_tty();
 	if (tty) {
-		tty_pgrp = tty->pgrp;
+		tty_pgrp = get_pid(tty->pgrp);
 		mutex_unlock(&tty_mutex);
 		/* XXX: here we race, there is nothing protecting tty */
 		if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
 			tty_vhangup(tty);
-	} else {
-		pid_t old_pgrp = current->signal->tty_old_pgrp;
+	} else if (on_exit) {
+		struct pid *old_pgrp;
+		spin_lock_irq(&current->sighand->siglock);
+		old_pgrp = current->signal->tty_old_pgrp;
+		current->signal->tty_old_pgrp = NULL;
+		spin_unlock_irq(&current->sighand->siglock);
 		if (old_pgrp) {
-			kill_pg(old_pgrp, SIGHUP, on_exit);
-			kill_pg(old_pgrp, SIGCONT, on_exit);
+			kill_pgrp(old_pgrp, SIGHUP, on_exit);
+			kill_pgrp(old_pgrp, SIGCONT, on_exit);
+			put_pid(old_pgrp);
 		}
 		mutex_unlock(&tty_mutex);
 		unlock_kernel();	
 		return;
 	}
-	if (tty_pgrp > 0) {
-		kill_pg(tty_pgrp, SIGHUP, on_exit);
+	if (tty_pgrp) {
+		kill_pgrp(tty_pgrp, SIGHUP, on_exit);
 		if (!on_exit)
-			kill_pg(tty_pgrp, SIGCONT, on_exit);
+			kill_pgrp(tty_pgrp, SIGCONT, on_exit);
+		put_pid(tty_pgrp);
 	}
 
 	spin_lock_irq(&current->sighand->siglock);
+	tty_pgrp = current->signal->tty_old_pgrp;
 	current->signal->tty_old_pgrp = 0;
-	session = process_session(current);
 	spin_unlock_irq(&current->sighand->siglock);
+	put_pid(tty_pgrp);
 
 	mutex_lock(&tty_mutex);
 	/* It is possible that do_tty_hangup has free'd this tty */
 	tty = get_current_tty();
 	if (tty) {
-		tty->session = 0;
-		tty->pgrp = 0;
+		put_pid(tty->session);
+		put_pid(tty->pgrp);
+		tty->session = NULL;
+		tty->pgrp = NULL;
 	} else {
 #ifdef TTY_DEBUG_HANGUP
 		printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
@@ -1544,7 +1555,7 @@
 
 	/* Now clear signal->tty under the lock */
 	read_lock(&tasklist_lock);
-	session_clear_tty(session);
+	session_clear_tty(task_session(current));
 	read_unlock(&tasklist_lock);
 	unlock_kernel();
 }
@@ -2481,6 +2492,7 @@
 	int index;
 	dev_t device = inode->i_rdev;
 	unsigned short saved_flags = filp->f_flags;
+	struct pid *old_pgrp;
 
 	nonseekable_open(inode, filp);
 	
@@ -2574,15 +2586,17 @@
 		goto retry_open;
 	}
 
+	old_pgrp = NULL;
 	mutex_lock(&tty_mutex);
 	spin_lock_irq(&current->sighand->siglock);
 	if (!noctty &&
 	    current->signal->leader &&
 	    !current->signal->tty &&
-	    tty->session == 0)
-		__proc_set_tty(current, tty);
+	    tty->session == NULL)
+		old_pgrp = __proc_set_tty(current, tty);
 	spin_unlock_irq(&current->sighand->siglock);
 	mutex_unlock(&tty_mutex);
+	put_pid(old_pgrp);
 	return 0;
 }
 
@@ -2721,9 +2735,18 @@
 		return retval;
 
 	if (on) {
+		enum pid_type type;
+		struct pid *pid;
 		if (!waitqueue_active(&tty->read_wait))
 			tty->minimum_to_wake = 1;
-		retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0);
+		if (tty->pgrp) {
+			pid = tty->pgrp;
+			type = PIDTYPE_PGID;
+		} else {
+			pid = task_pid(current);
+			type = PIDTYPE_PID;
+		}
+		retval = __f_setown(filp, pid, type, 0);
 		if (retval)
 			return retval;
 	} else {
@@ -2825,10 +2848,10 @@
 		}
 	}
 #endif
-	if (tty->pgrp > 0)
-		kill_pg(tty->pgrp, SIGWINCH, 1);
-	if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0))
-		kill_pg(real_tty->pgrp, SIGWINCH, 1);
+	if (tty->pgrp)
+		kill_pgrp(tty->pgrp, SIGWINCH, 1);
+	if ((real_tty->pgrp != tty->pgrp) && real_tty->pgrp)
+		kill_pgrp(real_tty->pgrp, SIGWINCH, 1);
 	tty->winsize = tmp_ws;
 	real_tty->winsize = tmp_ws;
 done:
@@ -2913,8 +2936,7 @@
 static int tiocsctty(struct tty_struct *tty, int arg)
 {
 	int ret = 0;
-	if (current->signal->leader &&
-			(process_session(current) == tty->session))
+	if (current->signal->leader && (task_session(current) == tty->session))
 		return ret;
 
 	mutex_lock(&tty_mutex);
@@ -2927,7 +2949,7 @@
 		goto unlock;
 	}
 
-	if (tty->session > 0) {
+	if (tty->session) {
 		/*
 		 * This tty is already the controlling
 		 * tty for another session group!
@@ -2970,7 +2992,7 @@
 	 */
 	if (tty == real_tty && current->signal->tty != real_tty)
 		return -ENOTTY;
-	return put_user(real_tty->pgrp, p);
+	return put_user(pid_nr(real_tty->pgrp), p);
 }
 
 /**
@@ -2987,7 +3009,8 @@
 
 static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
 {
-	pid_t pgrp;
+	struct pid *pgrp;
+	pid_t pgrp_nr;
 	int retval = tty_check_change(real_tty);
 
 	if (retval == -EIO)
@@ -2996,16 +3019,26 @@
 		return retval;
 	if (!current->signal->tty ||
 	    (current->signal->tty != real_tty) ||
-	    (real_tty->session != process_session(current)))
+	    (real_tty->session != task_session(current)))
 		return -ENOTTY;
-	if (get_user(pgrp, p))
+	if (get_user(pgrp_nr, p))
 		return -EFAULT;
-	if (pgrp < 0)
+	if (pgrp_nr < 0)
 		return -EINVAL;
-	if (session_of_pgrp(pgrp) != process_session(current))
-		return -EPERM;
-	real_tty->pgrp = pgrp;
-	return 0;
+	rcu_read_lock();
+	pgrp = find_pid(pgrp_nr);
+	retval = -ESRCH;
+	if (!pgrp)
+		goto out_unlock;
+	retval = -EPERM;
+	if (session_of_pgrp(pgrp) != task_session(current))
+		goto out_unlock;
+	retval = 0;
+	put_pid(real_tty->pgrp);
+	real_tty->pgrp = get_pid(pgrp);
+out_unlock:
+	rcu_read_unlock();
+	return retval;
 }
 
 /**
@@ -3028,9 +3061,9 @@
 	*/
 	if (tty == real_tty && current->signal->tty != real_tty)
 		return -ENOTTY;
-	if (real_tty->session <= 0)
+	if (!real_tty->session)
 		return -ENOTTY;
-	return put_user(real_tty->session, p);
+	return put_user(pid_nr(real_tty->session), p);
 }
 
 /**
@@ -3330,7 +3363,7 @@
 	tty_hangup(tty);
 #else
 	struct task_struct *g, *p;
-	int session;
+	struct pid *session;
 	int		i;
 	struct file	*filp;
 	struct fdtable *fdt;
@@ -3346,12 +3379,12 @@
 	
 	read_lock(&tasklist_lock);
 	/* Kill the entire session */
-	do_each_task_pid(session, PIDTYPE_SID, p) {
+	do_each_pid_task(session, PIDTYPE_SID, p) {
 		printk(KERN_NOTICE "SAK: killed process %d"
 			" (%s): process_session(p)==tty->session\n",
 			p->pid, p->comm);
 		send_sig(SIGKILL, p, 1);
-	} while_each_task_pid(session, PIDTYPE_SID, p);
+	} while_each_pid_task(session, PIDTYPE_SID, p);
 	/* Now kill any processes that happen to have the
 	 * tty open.
 	 */
@@ -3520,7 +3553,8 @@
 	memset(tty, 0, sizeof(struct tty_struct));
 	tty->magic = TTY_MAGIC;
 	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
-	tty->pgrp = -1;
+	tty->session = NULL;
+	tty->pgrp = NULL;
 	tty->overrun_time = jiffies;
 	tty->buf.head = tty->buf.tail = NULL;
 	tty_buffer_init(tty);
@@ -3791,21 +3825,28 @@
 }
 EXPORT_SYMBOL(proc_clear_tty);
 
-void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
+static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
 {
+	struct pid *old_pgrp;
 	if (tty) {
-		tty->session = process_session(tsk);
-		tty->pgrp = process_group(tsk);
+		tty->session = get_pid(task_session(tsk));
+		tty->pgrp = get_pid(task_pgrp(tsk));
 	}
+	old_pgrp = tsk->signal->tty_old_pgrp;
 	tsk->signal->tty = tty;
-	tsk->signal->tty_old_pgrp = 0;
+	tsk->signal->tty_old_pgrp = NULL;
+	return old_pgrp;
 }
 
 void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
 {
+	struct pid *old_pgrp;
+
 	spin_lock_irq(&tsk->sighand->siglock);
-	__proc_set_tty(tsk, tty);
+	old_pgrp = __proc_set_tty(tsk, tty);
 	spin_unlock_irq(&tsk->sighand->siglock);
+
+	put_pid(old_pgrp);
 }
 
 struct tty_struct *get_current_tty(void)
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 9438512..13faf8d 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -872,7 +872,7 @@
 	return ret;
 }
 
-struct file_operations viotap_fops = {
+const struct file_operations viotap_fops = {
 	owner: THIS_MODULE,
 	read: viotap_read,
 	write: viotap_write,
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 13299b8..94ce3e7 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -210,7 +210,7 @@
  */
 int (*console_blank_hook)(int);
 
-static struct timer_list console_timer;
+static DEFINE_TIMER(console_timer, blank_screen_t, 0, 0);
 static int blank_state;
 static int blank_timer_expired;
 enum {
@@ -866,8 +866,8 @@
 		ws.ws_col = vc->vc_cols;
 		ws.ws_ypixel = vc->vc_scan_lines;
 		if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
-		    vc->vc_tty->pgrp > 0)
-			kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1);
+		    vc->vc_tty->pgrp)
+			kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
 		*cws = ws;
 	}
 
@@ -2625,8 +2625,6 @@
 	for (i = 0; i < MAX_NR_CONSOLES; i++)
 		con_driver_map[i] = conswitchp;
 
-	init_timer(&console_timer);
-	console_timer.function = blank_screen_t;
 	if (blankinterval) {
 		blank_state = blank_normal_wait;
 		mod_timer(&console_timer, jiffies + blankinterval);
diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c
index bf25d0a..e5b2c2e 100644
--- a/drivers/char/watchdog/alim7101_wdt.c
+++ b/drivers/char/watchdog/alim7101_wdt.c
@@ -417,10 +417,8 @@
 module_exit(alim7101_wdt_unload);
 
 static struct pci_device_id alim7101_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
 	{ }
 };
 
diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c
index 7eac922..fd8a44a 100644
--- a/drivers/char/watchdog/iTCO_wdt.c
+++ b/drivers/char/watchdog/iTCO_wdt.c
@@ -539,7 +539,7 @@
  *	Kernel Interfaces
  */
 
-static struct file_operations iTCO_wdt_fops = {
+static const struct file_operations iTCO_wdt_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.write =	iTCO_wdt_write,
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
index 6c6f973..84074a6 100644
--- a/drivers/char/watchdog/omap_wdt.c
+++ b/drivers/char/watchdog/omap_wdt.c
@@ -230,7 +230,7 @@
 	}
 }
 
-static struct file_operations omap_wdt_fops = {
+static const struct file_operations omap_wdt_fops = {
 	.owner = THIS_MODULE,
 	.write = omap_wdt_write,
 	.ioctl = omap_wdt_ioctl,
diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c
index 1d447e3..a77a907 100644
--- a/drivers/char/watchdog/pc87413_wdt.c
+++ b/drivers/char/watchdog/pc87413_wdt.c
@@ -526,7 +526,7 @@
 
 /* -- Module's structures ---------------------------------------*/
 
-static struct file_operations pc87413_fops = {
+static const struct file_operations pc87413_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.write		= pc87413_write,
diff --git a/drivers/char/watchdog/pnx4008_wdt.c b/drivers/char/watchdog/pnx4008_wdt.c
index 3a55fc6..ff6f1ca 100644
--- a/drivers/char/watchdog/pnx4008_wdt.c
+++ b/drivers/char/watchdog/pnx4008_wdt.c
@@ -238,7 +238,7 @@
 	return 0;
 }
 
-static struct file_operations pnx4008_wdt_fops = {
+static const struct file_operations pnx4008_wdt_fops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 	.write = pnx4008_wdt_write,
diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c
index 7576a13..b467883 100644
--- a/drivers/char/watchdog/rm9k_wdt.c
+++ b/drivers/char/watchdog/rm9k_wdt.c
@@ -95,7 +95,7 @@
 
 
 /* Kernel interfaces */
-static struct file_operations fops = {
+static const struct file_operations fops = {
 	.owner		= THIS_MODULE,
 	.open		= wdt_gpi_open,
 	.release	= wdt_gpi_release,
diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c
index 9f56913..a9681d5 100644
--- a/drivers/char/watchdog/smsc37b787_wdt.c
+++ b/drivers/char/watchdog/smsc37b787_wdt.c
@@ -510,7 +510,7 @@
 
 /* -- Module's structures ---------------------------------------*/
 
-static struct file_operations wb_smsc_wdt_fops =
+static const struct file_operations wb_smsc_wdt_fops =
 {
 	.owner          = THIS_MODULE,
 	.llseek		= no_llseek,
diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c
index 7768b55..c960ec1 100644
--- a/drivers/char/watchdog/w83697hf_wdt.c
+++ b/drivers/char/watchdog/w83697hf_wdt.c
@@ -323,7 +323,7 @@
  *	Kernel Interfaces
  */
 
-static struct file_operations wdt_fops = {
+static const struct file_operations wdt_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.write		= wdt_write,
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index c82bc0e..8bcc887 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -285,8 +285,9 @@
 	if (!pvt->map_type)
 		row = 7 - row;
 
-	edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel,
-		"e752x CE");
+	/* e752x mc reads 34:6 of the DRAM linear address */
+	edac_mc_handle_ce(mci, page, offset_in_page(sec1_add << 4),
+			sec1_syndrome, row, channel, "e752x CE");
 }
 
 static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
@@ -319,8 +320,10 @@
 			((block_page >> 1) & 3) :
 			edac_mc_find_csrow_by_page(mci, block_page);
 
-		edac_mc_handle_ue(mci, block_page, 0, row,
-			"e752x UE from Read");
+		/* e752x mc reads 34:6 of the DRAM linear address */
+		edac_mc_handle_ue(mci, block_page,
+					offset_in_page(error_2b << 4),
+					row, "e752x UE from Read");
 	}
 	if (error_one & 0x0404) {
 		error_2b = scrb_add;
@@ -333,8 +336,10 @@
 			((block_page >> 1) & 3) :
 			edac_mc_find_csrow_by_page(mci, block_page);
 
-		edac_mc_handle_ue(mci, block_page, 0, row,
-				"e752x UE from Scruber");
+		/* e752x mc reads 34:6 of the DRAM linear address */
+		edac_mc_handle_ue(mci, block_page,
+					offset_in_page(error_2b << 4),
+					row, "e752x UE from Scruber");
 	}
 }
 
@@ -556,17 +561,17 @@
 	error32 = (stat32 >> 16) & 0x3ff;
 	stat32 = stat32 & 0x3ff;
 
-	if(stat32 & 0x083)
-		sysbus_error(1, stat32 & 0x083, error_found, handle_error);
+	if(stat32 & 0x087)
+		sysbus_error(1, stat32 & 0x087, error_found, handle_error);
 
-	if(stat32 & 0x37c)
-		sysbus_error(0, stat32 & 0x37c, error_found, handle_error);
+	if(stat32 & 0x378)
+		sysbus_error(0, stat32 & 0x378, error_found, handle_error);
 
-	if(error32 & 0x083)
-		sysbus_error(1, error32 & 0x083, error_found, handle_error);
+	if(error32 & 0x087)
+		sysbus_error(1, error32 & 0x087, error_found, handle_error);
 
-	if(error32 & 0x37c)
-		sysbus_error(0, error32 & 0x37c, error_found, handle_error);
+	if(error32 & 0x378)
+		sysbus_error(0, error32 & 0x378, error_found, handle_error);
 }
 
 static void e752x_check_membuf (struct e752x_error_info *info,
@@ -782,7 +787,12 @@
 	u8 value;
 	u32 dra, drc, cumul_size;
 
-	pci_read_config_dword(pdev, E752X_DRA, &dra);
+	dra = 0;
+	for (index=0; index < 4; index++) {
+		u8 dra_reg;
+		pci_read_config_byte(pdev, E752X_DRA+index, &dra_reg);
+		dra |= dra_reg << (index * 8);
+	}
 	pci_read_config_dword(pdev, E752X_DRC, &drc);
 	drc_chan = dual_channel_active(ddrcsr);
 	drc_drbg = drc_chan + 1;  /* 128 in dual mode, 64 in single */
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 1b4fc92..7b62230 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -927,6 +927,57 @@
 	return count;
 }
 
+/* memory scrubbing */
+static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
+					const char *data, size_t count)
+{
+	u32 bandwidth = -1;
+
+	if (mci->set_sdram_scrub_rate) {
+
+		memctrl_int_store(&bandwidth, data, count);
+
+		if (!(*mci->set_sdram_scrub_rate)(mci, &bandwidth)) {
+			edac_printk(KERN_DEBUG, EDAC_MC,
+				"Scrub rate set successfully, applied: %d\n",
+				bandwidth);
+		} else {
+			/* FIXME: error codes maybe? */
+			edac_printk(KERN_DEBUG, EDAC_MC,
+				"Scrub rate set FAILED, could not apply: %d\n",
+				bandwidth);
+		}
+	} else {
+		/* FIXME: produce "not implemented" ERROR for user-side. */
+		edac_printk(KERN_WARNING, EDAC_MC,
+			"Memory scrubbing 'set'control is not implemented!\n");
+	}
+	return count;
+}
+
+static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
+{
+	u32 bandwidth = -1;
+
+	if (mci->get_sdram_scrub_rate) {
+		if (!(*mci->get_sdram_scrub_rate)(mci, &bandwidth)) {
+			edac_printk(KERN_DEBUG, EDAC_MC,
+				"Scrub rate successfully, fetched: %d\n",
+				bandwidth);
+		} else {
+			/* FIXME: error codes maybe? */
+			edac_printk(KERN_DEBUG, EDAC_MC,
+				"Scrub rate fetch FAILED, got: %d\n",
+				bandwidth);
+		}
+	} else {
+		/* FIXME: produce "not implemented" ERROR for user-side.  */
+		edac_printk(KERN_WARNING, EDAC_MC,
+			"Memory scrubbing 'get' control is not implemented!\n");
+	}
+	return sprintf(data, "%d\n", bandwidth);
+}
+
 /* default attribute files for the MCI object */
 static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
 {
@@ -1033,6 +1084,9 @@
 MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
 MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
 
+/* memory scrubber attribute file */
+MCIDEV_ATTR(sdram_scrub_rate,S_IRUGO|S_IWUSR,mci_sdram_scrub_rate_show,mci_sdram_scrub_rate_store);
+
 static struct mcidev_attribute *mci_attr[] = {
 	&mci_attr_reset_counters,
 	&mci_attr_mc_name,
@@ -1042,6 +1096,7 @@
 	&mci_attr_ce_noinfo_count,
 	&mci_attr_ue_count,
 	&mci_attr_ce_count,
+	&mci_attr_sdram_scrub_rate,
 	NULL
 };
 
@@ -1442,11 +1497,11 @@
 	/* set load time so that error rate can be tracked */
 	mci->start_time = jiffies;
 
-        if (edac_create_sysfs_mci_device(mci)) {
-                edac_mc_printk(mci, KERN_WARNING,
+	if (edac_create_sysfs_mci_device(mci)) {
+		edac_mc_printk(mci, KERN_WARNING,
 			"failed to create sysfs device\n");
-                goto fail1;
-        }
+		goto fail1;
+	}
 
 	/* Report action taken */
 	edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n",
@@ -1703,6 +1758,116 @@
 EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info);
 
 
+/*************************************************************
+ * On Fully Buffered DIMM modules, this help function is
+ * called to process UE events
+ */
+void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
+				unsigned int csrow,
+				unsigned int channela,
+				unsigned int channelb,
+				char *msg)
+{
+	int len = EDAC_MC_LABEL_LEN * 4;
+	char labels[len + 1];
+	char *pos = labels;
+	int chars;
+
+	if (csrow >= mci->nr_csrows) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: row out of range (%d >= %d)\n",
+			csrow, mci->nr_csrows);
+		edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	if (channela >= mci->csrows[csrow].nr_channels) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: channel-a out of range "
+			"(%d >= %d)\n",
+			channela, mci->csrows[csrow].nr_channels);
+		edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	if (channelb >= mci->csrows[csrow].nr_channels) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: channel-b out of range "
+			"(%d >= %d)\n",
+			channelb, mci->csrows[csrow].nr_channels);
+		edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	mci->ue_count++;
+	mci->csrows[csrow].ue_count++;
+
+	/* Generate the DIMM labels from the specified channels */
+	chars = snprintf(pos, len + 1, "%s",
+			 mci->csrows[csrow].channels[channela].label);
+	len -= chars; pos += chars;
+	chars = snprintf(pos, len + 1, "-%s",
+			 mci->csrows[csrow].channels[channelb].label);
+
+	if (log_ue)
+		edac_mc_printk(mci, KERN_EMERG,
+			"UE row %d, channel-a= %d channel-b= %d "
+			"labels \"%s\": %s\n", csrow, channela, channelb,
+			labels, msg);
+
+	if (panic_on_ue)
+		panic("UE row %d, channel-a= %d channel-b= %d "
+				"labels \"%s\": %s\n", csrow, channela,
+				channelb, labels, msg);
+}
+EXPORT_SYMBOL(edac_mc_handle_fbd_ue);
+
+/*************************************************************
+ * On Fully Buffered DIMM modules, this help function is
+ * called to process CE events
+ */
+void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
+			   unsigned int csrow,
+			   unsigned int channel,
+			   char *msg)
+{
+
+	/* Ensure boundary values */
+	if (csrow >= mci->nr_csrows) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: row out of range (%d >= %d)\n",
+			csrow, mci->nr_csrows);
+		edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+	if (channel >= mci->csrows[csrow].nr_channels) {
+		/* something is wrong */
+		edac_mc_printk(mci, KERN_ERR,
+			"INTERNAL ERROR: channel out of range (%d >= %d)\n",
+			channel, mci->csrows[csrow].nr_channels);
+		edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+		return;
+	}
+
+	if (log_ce)
+		/* FIXME - put in DIMM location */
+		edac_mc_printk(mci, KERN_WARNING,
+			"CE row %d, channel %d, label \"%s\": %s\n",
+			csrow, channel,
+			mci->csrows[csrow].channels[channel].label,
+			msg);
+
+	mci->ce_count++;
+	mci->csrows[csrow].ce_count++;
+	mci->csrows[csrow].channels[channel].ce_count++;
+}
+EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
+
+
 /*
  * Iterate over all MC instances and check for ECC, et al, errors
  */
@@ -1806,7 +1971,7 @@
 	debugf0("%s()\n", __func__);
 	kthread_stop(edac_thread);
 
-        /* tear down the sysfs device */
+	/* tear down the sysfs device */
 	edac_sysfs_memctrl_teardown();
 	edac_sysfs_pci_teardown();
 }
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index a1cfd4e..713444c 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -123,7 +123,9 @@
 	MEM_RDR,		/* Registered single data rate SDRAM */
 	MEM_DDR,		/* Double data rate SDRAM */
 	MEM_RDDR,		/* Registered Double data rate SDRAM */
-	MEM_RMBS		/* Rambus DRAM */
+	MEM_RMBS,		/* Rambus DRAM */
+	MEM_DDR2,               /* DDR2 RAM */
+	MEM_FB_DDR2,            /* fully buffered DDR2 */
 };
 
 #define MEM_FLAG_EMPTY		BIT(MEM_EMPTY)
@@ -137,6 +139,8 @@
 #define MEM_FLAG_DDR		BIT(MEM_DDR)
 #define MEM_FLAG_RDDR		BIT(MEM_RDDR)
 #define MEM_FLAG_RMBS		BIT(MEM_RMBS)
+#define MEM_FLAG_DDR2           BIT(MEM_DDR2)
+#define MEM_FLAG_FB_DDR2        BIT(MEM_FB_DDR2)
 
 /* chipset Error Detection and Correction capabilities and mode */
 enum edac_type {
@@ -315,8 +319,21 @@
 	unsigned long scrub_cap;	/* chipset scrub capabilities */
 	enum scrub_type scrub_mode;	/* current scrub mode */
 
+	/* Translates sdram memory scrub rate given in bytes/sec to the
+	   internal representation and configures whatever else needs
+	   to be configured.
+	*/
+	int (*set_sdram_scrub_rate) (struct mem_ctl_info *mci, u32 *bw);
+
+	/* Get the current sdram memory scrub rate from the internal
+	   representation and converts it to the closest matching
+	   bandwith in bytes/sec.
+	*/
+	int (*get_sdram_scrub_rate) (struct mem_ctl_info *mci, u32 *bw);
+
 	/* pointer to edac checking routine */
 	void (*edac_check) (struct mem_ctl_info * mci);
+
 	/*
 	 * Remaps memory pages: controller pages to physical pages.
 	 * For most MC's, this will be NULL.
@@ -441,6 +458,15 @@
 		int row, const char *msg);
 extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
 		const char *msg);
+extern void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
+		unsigned int csrow,
+		unsigned int channel0,
+		unsigned int channel1,
+		char *msg);
+extern void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
+		unsigned int csrow,
+		unsigned int channel,
+		char *msg);
 
 /*
  * This kmalloc's and initializes all the structures.
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 4ee56de..214fbb1 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -308,7 +308,7 @@
 	return single_open(file, dbg_show, inode->i_private);
 }
 
-static struct file_operations debug_fops = {
+static const struct file_operations debug_fops = {
 	.open		= dbg_tps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index ac5bd2a..cb4fa9b 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -392,7 +392,7 @@
 	return 0;
 }
 
-static struct file_operations i2cdev_fops = {
+static const struct file_operations i2cdev_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= i2cdev_read,
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index ad49bd8..30a5780 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -548,7 +548,7 @@
 	return single_open(file, &ide_drivers_show, NULL);
 }
 
-static struct file_operations ide_drivers_operations = {
+static const struct file_operations ide_drivers_operations = {
 	.open		= ide_drivers_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index b3bcd1d..c6eec04 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -4779,7 +4779,7 @@
 /*
  *	Our character device supporting functions, passed to register_chrdev.
  */
-static struct file_operations idetape_fops = {
+static const struct file_operations idetape_fops = {
 	.owner		= THIS_MODULE,
 	.read		= idetape_chrdev_read,
 	.write		= idetape_chrdev_write,
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 55d6ae6..dee9529 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2147,7 +2147,7 @@
 }
 
 static struct cdev dv1394_cdev;
-static struct file_operations dv1394_fops=
+static const struct file_operations dv1394_fops=
 {
 	.owner =	THIS_MODULE,
 	.poll =         dv1394_poll,
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index a77a832..aa9ca83 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -3013,7 +3013,7 @@
 };
 
 static struct cdev raw1394_cdev;
-static struct file_operations raw1394_fops = {
+static const struct file_operations raw1394_fops = {
 	.owner = THIS_MODULE,
 	.read = raw1394_read,
 	.write = raw1394_write,
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index f4d1ec0..95ca26d 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1277,7 +1277,7 @@
 #endif
 
 static struct cdev video1394_cdev;
-static struct file_operations video1394_fops=
+static const struct file_operations video1394_fops=
 {
 	.owner =	THIS_MODULE,
 	.unlocked_ioctl = video1394_ioctl,
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index f15220a..ee51d79 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1221,7 +1221,7 @@
 	kfree(dev);
 }
 
-static struct file_operations ucm_fops = {
+static const struct file_operations ucm_fops = {
 	.owner 	 = THIS_MODULE,
 	.open 	 = ib_ucm_open,
 	.release = ib_ucm_close,
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index e2e8d32..6b81b98 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -833,7 +833,7 @@
 	return 0;
 }
 
-static struct file_operations ucma_fops = {
+static const struct file_operations ucma_fops = {
 	.owner 	 = THIS_MODULE,
 	.open 	 = ucma_open,
 	.release = ucma_close,
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 807fbd6..c069ebe 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -771,7 +771,7 @@
 	return 0;
 }
 
-static struct file_operations umad_fops = {
+static const struct file_operations umad_fops = {
 	.owner 	 	= THIS_MODULE,
 	.read 	 	= ib_umad_read,
 	.write 	 	= ib_umad_write,
@@ -846,7 +846,7 @@
 	return ret;
 }
 
-static struct file_operations umad_sm_fops = {
+static const struct file_operations umad_sm_fops = {
 	.owner 	 = THIS_MODULE,
 	.open 	 = ib_umad_sm_open,
 	.release = ib_umad_sm_close
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index a617ca7..f8bc822 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -375,7 +375,7 @@
 	return 0;
 }
 
-static struct file_operations uverbs_event_fops = {
+static const struct file_operations uverbs_event_fops = {
 	.owner	 = THIS_MODULE,
 	.read 	 = ib_uverbs_event_read,
 	.poll    = ib_uverbs_event_poll,
@@ -679,14 +679,14 @@
 	return 0;
 }
 
-static struct file_operations uverbs_fops = {
+static const struct file_operations uverbs_fops = {
 	.owner 	 = THIS_MODULE,
 	.write 	 = ib_uverbs_write,
 	.open 	 = ib_uverbs_open,
 	.release = ib_uverbs_close
 };
 
-static struct file_operations uverbs_mmap_fops = {
+static const struct file_operations uverbs_mmap_fops = {
 	.owner 	 = THIS_MODULE,
 	.write 	 = ib_uverbs_write,
 	.mmap    = ib_uverbs_mmap,
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index 28c087b..0f13a21 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -59,7 +59,7 @@
 static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
 				size_t count, loff_t *off);
 
-static struct file_operations diag_file_ops = {
+static const struct file_operations diag_file_ops = {
 	.owner = THIS_MODULE,
 	.write = ipath_diag_write,
 	.read = ipath_diag_read,
@@ -71,7 +71,7 @@
 				   const char __user *data,
 				   size_t count, loff_t *off);
 
-static struct file_operations diagpkt_file_ops = {
+static const struct file_operations diagpkt_file_ops = {
 	.owner = THIS_MODULE,
 	.write = ipath_diagpkt_write,
 };
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index b932bcb..5d64ff8 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -54,7 +54,7 @@
 static unsigned int ipath_poll(struct file *, struct poll_table_struct *);
 static int ipath_mmap(struct file *, struct vm_area_struct *);
 
-static struct file_operations ipath_file_ops = {
+static const struct file_operations ipath_file_ops = {
 	.owner = THIS_MODULE,
 	.write = ipath_write,
 	.open = ipath_open,
@@ -2153,7 +2153,7 @@
 
 static struct class *ipath_class;
 
-static int init_cdev(int minor, char *name, struct file_operations *fops,
+static int init_cdev(int minor, char *name, const struct file_operations *fops,
 		     struct cdev **cdevp, struct class_device **class_devp)
 {
 	const dev_t dev = MKDEV(IPATH_MAJOR, minor);
@@ -2210,7 +2210,7 @@
 	return ret;
 }
 
-int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
 		    struct cdev **cdevp, struct class_device **class_devp)
 {
 	return init_cdev(minor, name, fops, cdevp, class_devp);
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 79a60f0..5b40a84 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -47,7 +47,7 @@
 static struct super_block *ipath_super;
 
 static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
-			 int mode, struct file_operations *fops,
+			 int mode, const struct file_operations *fops,
 			 void *data)
 {
 	int error;
@@ -81,7 +81,7 @@
 
 static int create_file(const char *name, mode_t mode,
 		       struct dentry *parent, struct dentry **dentry,
-		       struct file_operations *fops, void *data)
+		       const struct file_operations *fops, void *data)
 {
 	int error;
 
@@ -105,7 +105,7 @@
 				       sizeof ipath_stats);
 }
 
-static struct file_operations atomic_stats_ops = {
+static const struct file_operations atomic_stats_ops = {
 	.read = atomic_stats_read,
 };
 
@@ -127,7 +127,7 @@
 				       sizeof counters);
 }
 
-static struct file_operations atomic_counters_ops = {
+static const struct file_operations atomic_counters_ops = {
 	.read = atomic_counters_read,
 };
 
@@ -166,7 +166,7 @@
 				       sizeof nodeinfo);
 }
 
-static struct file_operations atomic_node_info_ops = {
+static const struct file_operations atomic_node_info_ops = {
 	.read = atomic_node_info_read,
 };
 
@@ -291,7 +291,7 @@
 				       sizeof portinfo);
 }
 
-static struct file_operations atomic_port_info_ops = {
+static const struct file_operations atomic_port_info_ops = {
 	.read = atomic_port_info_read,
 };
 
@@ -394,7 +394,7 @@
 	return ret;
 }
 
-static struct file_operations flash_ops = {
+static const struct file_operations flash_ops = {
 	.read = flash_read,
 	.write = flash_write,
 };
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 986b212..6d8d05f 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -593,7 +593,7 @@
 void ipath_disarm_senderrbufs(struct ipath_devdata *);
 
 struct file_operations;
-int ipath_cdev_init(int minor, char *name, struct file_operations *fops,
+int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
 		    struct cdev **cdevp, struct class_device **class_devp);
 void ipath_cdev_cleanup(struct cdev **cdevp,
 			struct class_device **class_devp);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index f1cb836..44c1741 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -146,7 +146,7 @@
 	return 0;
 }
 
-static struct file_operations ipoib_mcg_fops = {
+static const struct file_operations ipoib_mcg_fops = {
 	.owner   = THIS_MODULE,
 	.open    = ipoib_mcg_open,
 	.read    = seq_read,
@@ -252,7 +252,7 @@
 	return 0;
 }
 
-static struct file_operations ipoib_path_fops = {
+static const struct file_operations ipoib_path_fops = {
 	.owner   = THIS_MODULE,
 	.open    = ipoib_path_open,
 	.read    = seq_read,
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 7cf2b4f..14d4c049 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -482,7 +482,7 @@
 	return seq_open(file, &input_devices_seq_ops);
 }
 
-static struct file_operations input_devices_fileops = {
+static const struct file_operations input_devices_fileops = {
 	.owner		= THIS_MODULE,
 	.open		= input_proc_devices_open,
 	.poll		= input_proc_devices_poll,
@@ -533,7 +533,7 @@
 	return seq_open(file, &input_handlers_seq_ops);
 }
 
-static struct file_operations input_handlers_fileops = {
+static const struct file_operations input_handlers_fileops = {
 	.owner		= THIS_MODULE,
 	.open		= input_proc_handlers_open,
 	.read		= seq_read,
@@ -1142,7 +1142,7 @@
 	return err;
 }
 
-static struct file_operations input_fops = {
+static const struct file_operations input_fops = {
 	.owner = THIS_MODULE,
 	.open = input_open_file,
 };
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 31d5a13..ab76ea4 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -670,7 +670,7 @@
 #endif
 }
 
-static struct file_operations hp_sdc_rtc_fops = {
+static const struct file_operations hp_sdc_rtc_fops = {
         .owner =	THIS_MODULE,
         .llseek =	no_llseek,
         .read =		hp_sdc_rtc_read,
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 9516439..4255623 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -627,7 +627,7 @@
 	return retval;
 }
 
-static struct file_operations uinput_fops = {
+static const struct file_operations uinput_fops = {
 	.owner		= THIS_MODULE,
 	.open		= uinput_open,
 	.release	= uinput_release,
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 088ebc3..8873576 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -234,7 +234,7 @@
 	return 0;
 }
 
-static struct file_operations serio_raw_fops = {
+static const struct file_operations serio_raw_fops = {
 	.owner =	THIS_MODULE,
 	.open =		serio_raw_open,
 	.release =	serio_raw_release,
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index d22c022..db1260f 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -118,6 +118,15 @@
 };
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 
+/* FIXME: The following lock is a sledgehammer-workaround to a
+ * locking issue with the capiminor (and maybe other) data structure(s).
+ * Access to this data is done in a racy way and crashes the machine with
+ * a FritzCard DSL driver; sooner or later. This is a workaround
+ * which trades scalability vs stability, so it doesn't crash the kernel anymore.
+ * The correct (and scalable) fix for the issue seems to require
+ * an API change to the drivers... . */
+static DEFINE_SPINLOCK(workaround_lock);
+
 struct capincci {
 	struct capincci *next;
 	u32		 ncci;
@@ -589,6 +598,7 @@
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 	struct capincci *np;
 	u32 ncci;
+	unsigned long flags;
 
 	if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
 		u16 info = CAPIMSG_U16(skb->data, 12); // Info field
@@ -603,9 +613,11 @@
 		capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
 		up(&cdev->ncci_list_sem);
 	}
+	spin_lock_irqsave(&workaround_lock, flags);
 	if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {
 		skb_queue_tail(&cdev->recvqueue, skb);
 		wake_up_interruptible(&cdev->recvwait);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 		return;
 	}
 	ncci = CAPIMSG_CONTROL(skb->data);
@@ -615,6 +627,7 @@
 		printk(KERN_ERR "BUG: capi_signal: ncci not found\n");
 		skb_queue_tail(&cdev->recvqueue, skb);
 		wake_up_interruptible(&cdev->recvwait);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 		return;
 	}
 #ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -625,6 +638,7 @@
 	if (!mp) {
 		skb_queue_tail(&cdev->recvqueue, skb);
 		wake_up_interruptible(&cdev->recvwait);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 		return;
 	}
 
@@ -660,6 +674,7 @@
 		wake_up_interruptible(&cdev->recvwait);
 	}
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+	spin_unlock_irqrestore(&workaround_lock, flags);
 }
 
 /* -------- file_operations for capidev ----------------------------- */
@@ -988,7 +1003,7 @@
 	return 0;
 }
 
-static struct file_operations capi_fops =
+static const struct file_operations capi_fops =
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
@@ -1006,6 +1021,7 @@
 static int capinc_tty_open(struct tty_struct * tty, struct file * file)
 {
 	struct capiminor *mp;
+	unsigned long flags;
 
 	if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == 0)
 		return -ENXIO;
@@ -1014,6 +1030,7 @@
 
 	tty->driver_data = (void *)mp;
 
+	spin_lock_irqsave(&workaround_lock, flags);
 	if (atomic_read(&mp->ttyopencount) == 0)
 		mp->tty = tty;
 	atomic_inc(&mp->ttyopencount);
@@ -1021,6 +1038,7 @@
 	printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount));
 #endif
 	handle_minor_recv(mp);
+	spin_unlock_irqrestore(&workaround_lock, flags);
 	return 0;
 }
 
@@ -1054,6 +1072,7 @@
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
+	unsigned long flags;
 
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count);
@@ -1066,6 +1085,7 @@
 		return 0;
 	}
 
+	spin_lock_irqsave(&workaround_lock, flags);
 	skb = mp->ttyskb;
 	if (skb) {
 		mp->ttyskb = NULL;
@@ -1076,6 +1096,7 @@
 	skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC);
 	if (!skb) {
 		printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n");
+		spin_unlock_irqrestore(&workaround_lock, flags);
 		return -ENOMEM;
 	}
 
@@ -1086,6 +1107,7 @@
 	mp->outbytes += skb->len;
 	(void)handle_minor_send(mp);
 	(void)handle_minor_recv(mp);
+	spin_unlock_irqrestore(&workaround_lock, flags);
 	return count;
 }
 
@@ -1093,6 +1115,7 @@
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
+	unsigned long flags;
 
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);
@@ -1105,10 +1128,12 @@
 		return;
 	}
 
+	spin_lock_irqsave(&workaround_lock, flags);
 	skb = mp->ttyskb;
 	if (skb) {
 		if (skb_tailroom(skb) > 0) {
 			*(skb_put(skb, 1)) = ch;
+			spin_unlock_irqrestore(&workaround_lock, flags);
 			return;
 		}
 		mp->ttyskb = NULL;
@@ -1124,12 +1149,14 @@
 	} else {
 		printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);
 	}
+	spin_unlock_irqrestore(&workaround_lock, flags);
 }
 
 static void capinc_tty_flush_chars(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
+	unsigned long flags;
 
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_flush_chars\n");
@@ -1142,6 +1169,7 @@
 		return;
 	}
 
+	spin_lock_irqsave(&workaround_lock, flags);
 	skb = mp->ttyskb;
 	if (skb) {
 		mp->ttyskb = NULL;
@@ -1150,6 +1178,7 @@
 		(void)handle_minor_send(mp);
 	}
 	(void)handle_minor_recv(mp);
+	spin_unlock_irqrestore(&workaround_lock, flags);
 }
 
 static int capinc_tty_write_room(struct tty_struct *tty)
@@ -1220,12 +1249,15 @@
 static void capinc_tty_unthrottle(struct tty_struct * tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
+	unsigned long flags;
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_unthrottle\n");
 #endif
 	if (mp) {
+		spin_lock_irqsave(&workaround_lock, flags);
 		mp->ttyinstop = 0;
 		handle_minor_recv(mp);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 	}
 }
 
@@ -1243,12 +1275,15 @@
 static void capinc_tty_start(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
+	unsigned long flags;
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_start\n");
 #endif
 	if (mp) {
+		spin_lock_irqsave(&workaround_lock, flags);
 		mp->ttyoutstop = 0;
 		(void)handle_minor_send(mp);
+		spin_unlock_irqrestore(&workaround_lock, flags);
 	}
 }
 
@@ -1456,7 +1491,7 @@
 
 static void __init proc_init(void)
 {
-    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int nelem = ARRAY_SIZE(procfsentries);
     int i;
 
     for (i=0; i < nelem; i++) {
@@ -1468,7 +1503,7 @@
 
 static void __exit proc_exit(void)
 {
-    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int nelem = ARRAY_SIZE(procfsentries);
     int i;
 
     for (i=nelem-1; i >= 0; i--) {
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index c4d438c..8cec9c3 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -2218,7 +2218,7 @@
 
 static void __init proc_init(void)
 {
-    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int nelem = ARRAY_SIZE(procfsentries);
     int i;
 
     for (i=0; i < nelem; i++) {
@@ -2230,7 +2230,7 @@
 
 static void __exit proc_exit(void)
 {
-    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int nelem = ARRAY_SIZE(procfsentries);
     int i;
 
     for (i=nelem-1; i >= 0; i--) {
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index ca9dc00..31f4fd8 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -113,14 +113,14 @@
 	return seq_open(file, &seq_contrstats_ops);
 }
 
-static struct file_operations proc_controller_ops = {
+static const struct file_operations proc_controller_ops = {
 	.open		= seq_controller_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
 	.release	= seq_release,
 };
 
-static struct file_operations proc_contrstats_ops = {
+static const struct file_operations proc_contrstats_ops = {
 	.open		= seq_contrstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -218,14 +218,14 @@
 	return seq_open(file, &seq_applstats_ops);
 }
 
-static struct file_operations proc_applications_ops = {
+static const struct file_operations proc_applications_ops = {
 	.open		= seq_applications_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
 	.release	= seq_release,
 };
 
-static struct file_operations proc_applstats_ops = {
+static const struct file_operations proc_applstats_ops = {
 	.open		= seq_applstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -302,7 +302,7 @@
 	return err;
 }
 
-static struct file_operations proc_driver_ops = {
+static const struct file_operations proc_driver_ops = {
 	.open		= seq_capi_driver_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
index 06967da..53a1890 100644
--- a/drivers/isdn/divert/divert_procfs.c
+++ b/drivers/isdn/divert/divert_procfs.c
@@ -256,7 +256,7 @@
 
 
 #ifdef CONFIG_PROC_FS
-static struct file_operations isdn_fops =
+static const struct file_operations isdn_fops =
 {
 	.owner          = THIS_MODULE,
 	.llseek         = no_llseek,
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig
index 708d47a..bcbb650 100644
--- a/drivers/isdn/gigaset/Kconfig
+++ b/drivers/isdn/gigaset/Kconfig
@@ -7,7 +7,13 @@
 	select CRC_CCITT
 	select BITREVERSE
 	help
-	  Say m here if you have a Gigaset or Sinus isdn device.
+	  This driver supports the Siemens Gigaset SX205/255 family of
+	  ISDN DECT bases, including the predecessors Gigaset 3070/3075
+	  and 4170/4175 and their T-Com versions Sinus 45isdn and Sinus
+	  721X.
+	  If you have one of these devices, say M here and for at least
+	  one of the connection specific parts that follow.
+	  This will build a module called "gigaset".
 
 if ISDN_DRV_GIGASET!=n
 
@@ -15,14 +21,25 @@
 	tristate "Gigaset base station support"
 	depends on ISDN_DRV_GIGASET && USB
 	help
-	  Say m here if you need to communicate with the base
-	  directly via USB.
+	  Say M here if you want to use the USB interface of the Gigaset
+	  base for connection to your system.
+	  This will build a module called "bas_gigaset".
 
 config GIGASET_M105
 	tristate "Gigaset M105 support"
 	depends on ISDN_DRV_GIGASET && USB
 	help
-	  Say m here if you need the driver for the Gigaset M105 device.
+	  Say M here if you want to connect to the Gigaset base via DECT
+	  using a Gigaset M105 (Sinus 45 Data 2) USB DECT device.
+	  This will build a module called "usb_gigaset".
+
+config GIGASET_M101
+	tristate "Gigaset M101 support"
+	depends on ISDN_DRV_GIGASET
+	help
+	  Say M here if you want to connect to the Gigaset base via DECT
+	  using a Gigaset M101 (Sinus 45 Data 1) RS232 DECT device.
+	  This will build a module called "ser_gigaset".
 
 config GIGASET_DEBUG
 	bool "Gigaset debugging"
diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile
index 9b9acf1..835b806 100644
--- a/drivers/isdn/gigaset/Makefile
+++ b/drivers/isdn/gigaset/Makefile
@@ -1,6 +1,8 @@
 gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o
 usb_gigaset-y := usb-gigaset.o asyncdata.o
 bas_gigaset-y := bas-gigaset.o isocdata.o
+ser_gigaset-y := ser-gigaset.o asyncdata.o
 
 obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o gigaset.o
 obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o gigaset.o
+obj-$(CONFIG_GIGASET_M105) += ser_gigaset.o gigaset.o
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 88e958f..ddf5e92 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -13,6 +13,11 @@
  * =====================================================================
  */
 
+/* not set by Kbuild when building both ser_gigaset and usb_gigaset */
+#ifndef KBUILD_MODNAME
+#define KBUILD_MODNAME "asy_gigaset"
+#endif
+
 #include "gigaset.h"
 #include <linux/crc-ccitt.h>
 #include <linux/bitrev.h>
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 4f75cce..b460a73 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -640,7 +640,6 @@
 		return NULL;
 	}
 	mutex_init(&cs->mutex);
-	mutex_lock(&cs->mutex);
 
 	gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
 	cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
@@ -738,6 +737,7 @@
 
 	++cs->cs_init;
 
+	/* set up character device */
 	gigaset_if_init(cs);
 
 	/* set up device sysfs */
@@ -753,11 +753,9 @@
 	add_timer(&cs->timer);
 
 	gig_dbg(DEBUG_INIT, "cs initialized");
-	mutex_unlock(&cs->mutex);
 	return cs;
 
 error:
-	mutex_unlock(&cs->mutex);
 	gig_dbg(DEBUG_INIT, "failed");
 	gigaset_freecs(cs);
 	return NULL;
@@ -908,20 +906,7 @@
 	gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN");
 	gigaset_schedule_event(cs);
 
-	if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
-		warn("%s: aborted", __func__);
-		//FIXME
-	}
-
-	if (atomic_read(&cs->mstate) != MS_LOCKED) {
-		//FIXME?
-		//gigaset_baud_rate(cs, B115200);
-		//gigaset_set_line_ctrl(cs, CS8);
-		//gigaset_set_modem_ctrl(cs, TIOCM_DTR|TIOCM_RTS, 0);
-		//cs->control_state = 0;
-	} else {
-		//FIXME use some saved values?
-	}
+	wait_event(cs->waitqueue, !cs->waiting);
 
 	cleanup_cs(cs);
 
@@ -944,10 +929,7 @@
 	gig_dbg(DEBUG_CMD, "scheduling STOP");
 	gigaset_schedule_event(cs);
 
-	if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) {
-		warn("%s: aborted", __func__);
-		//FIXME
-	}
+	wait_event(cs->waitqueue, !cs->waiting);
 
 	cleanup_cs(cs);
 
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 44f02db..4661e2c 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -1015,7 +1015,7 @@
 
 	cs->cmd_result = -ENODEV;
 	cs->waiting = 0;
-	wake_up_interruptible(&cs->waitqueue);
+	wake_up(&cs->waitqueue);
 }
 
 static void do_shutdown(struct cardstate *cs)
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index f13de20..eb50f3d 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -615,6 +615,8 @@
 		return;
 
 	tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs);
+
+	mutex_lock(&cs->mutex);
 	cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
 
 	if (!IS_ERR(cs->tty_dev))
@@ -623,6 +625,7 @@
 		warn("could not register device to the tty subsystem");
 		cs->tty_dev = NULL;
 	}
+	mutex_unlock(&cs->mutex);
 }
 
 void gigaset_if_free(struct cardstate *cs)
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index df988eb..8c0eb52 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -921,6 +921,8 @@
 			/* end of line */
 			gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
 				__func__, cbytes);
+			if (cbytes >= MAX_RESP_SIZE - 1)
+				dev_warn(cs->dev, "response too large\n");
 			cs->cbytes = cbytes;
 			gigaset_handle_modem_response(cs);
 			cbytes = 0;
@@ -929,8 +931,6 @@
 			/* advance in line buffer, checking for overflow */
 			if (cbytes < MAX_RESP_SIZE - 1)
 				cbytes++;
-			else
-				dev_warn(cs->dev, "response too large\n");
 		}
 	}
 
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
new file mode 100644
index 0000000..c8b7db6
--- /dev/null
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -0,0 +1,837 @@
+/* This is the serial hardware link layer (HLL) for the Gigaset 307x isdn
+ * DECT base (aka Sinus 45 isdn) using the RS232 DECT data module M101,
+ * written as a line discipline.
+ *
+ * =====================================================================
+ * 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.
+ * =====================================================================
+ */
+
+#include "gigaset.h"
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/poll.h>
+
+/* Version Information */
+#define DRIVER_AUTHOR "Tilman Schmidt"
+#define DRIVER_DESC "Serial Driver for Gigaset 307x using Siemens M101"
+
+#define GIGASET_MINORS     1
+#define GIGASET_MINOR      0
+#define GIGASET_MODULENAME "ser_gigaset"
+#define GIGASET_DEVNAME    "ttyGS"
+
+/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */
+#define IF_WRITEBUF 264
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_LDISC(N_GIGASET_M101);
+
+static int startmode = SM_ISDN;
+module_param(startmode, int, S_IRUGO);
+MODULE_PARM_DESC(startmode, "initial operation mode");
+static int cidmode = 1;
+module_param(cidmode, int, S_IRUGO);
+MODULE_PARM_DESC(cidmode, "stay in CID mode when idle");
+
+static struct gigaset_driver *driver;
+
+struct ser_cardstate {
+	struct platform_device	dev;
+	struct tty_struct	*tty;
+	atomic_t		refcnt;
+	struct mutex		dead_mutex;
+};
+
+static struct platform_driver device_driver = {
+	.driver = {
+		.name = GIGASET_MODULENAME,
+	},
+};
+
+static void flush_send_queue(struct cardstate *);
+
+/* transmit data from current open skb
+ * result: number of bytes sent or error code < 0
+ */
+static int write_modem(struct cardstate *cs)
+{
+	struct tty_struct *tty = cs->hw.ser->tty;
+	struct bc_state *bcs = &cs->bcs[0];	/* only one channel */
+	struct sk_buff *skb = bcs->tx_skb;
+	int sent;
+
+	if (!tty || !tty->driver || !skb)
+		return -EFAULT;
+
+	if (!skb->len) {
+		dev_kfree_skb_any(skb);
+		bcs->tx_skb = NULL;
+		return -EINVAL;
+	}
+
+	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+	sent = tty->driver->write(tty, skb->data, skb->len);
+	gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent);
+	if (sent < 0) {
+		/* error */
+		flush_send_queue(cs);
+		return sent;
+	}
+	skb_pull(skb, sent);
+	if (!skb->len) {
+		/* skb sent completely */
+		gigaset_skb_sent(bcs, skb);
+
+		gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
+			(unsigned long) skb);
+		dev_kfree_skb_any(skb);
+		bcs->tx_skb = NULL;
+	}
+	return sent;
+}
+
+/*
+ * transmit first queued command buffer
+ * result: number of bytes sent or error code < 0
+ */
+static int send_cb(struct cardstate *cs)
+{
+	struct tty_struct *tty = cs->hw.ser->tty;
+	struct cmdbuf_t *cb, *tcb;
+	unsigned long flags;
+	int sent = 0;
+
+	if (!tty || !tty->driver)
+		return -EFAULT;
+
+	cb = cs->cmdbuf;
+	if (!cb)
+		return 0;	/* nothing to do */
+
+	if (cb->len) {
+		set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+		sent = tty->driver->write(tty, cb->buf + cb->offset, cb->len);
+		if (sent < 0) {
+			/* error */
+			gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent);
+			flush_send_queue(cs);
+			return sent;
+		}
+		cb->offset += sent;
+		cb->len -= sent;
+		gig_dbg(DEBUG_OUTPUT, "send_cb: sent %d, left %u, queued %u",
+			sent, cb->len, cs->cmdbytes);
+	}
+
+	while (cb && !cb->len) {
+		spin_lock_irqsave(&cs->cmdlock, flags);
+		cs->cmdbytes -= cs->curlen;
+		tcb = cb;
+		cs->cmdbuf = cb = cb->next;
+		if (cb) {
+			cb->prev = NULL;
+			cs->curlen = cb->len;
+		} else {
+			cs->lastcmdbuf = NULL;
+			cs->curlen = 0;
+		}
+		spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+		if (tcb->wake_tasklet)
+			tasklet_schedule(tcb->wake_tasklet);
+		kfree(tcb);
+	}
+	return sent;
+}
+
+/*
+ * send queue tasklet
+ * If there is already a skb opened, put data to the transfer buffer
+ * by calling "write_modem".
+ * Otherwise take a new skb out of the queue.
+ */
+static void gigaset_modem_fill(unsigned long data)
+{
+	struct cardstate *cs = (struct cardstate *) data;
+	struct bc_state *bcs;
+	int sent = 0;
+
+	if (!cs || !(bcs = cs->bcs)) {
+		gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__);
+		return;
+	}
+	if (!bcs->tx_skb) {
+		/* no skb is being sent; send command if any */
+		sent = send_cb(cs);
+		gig_dbg(DEBUG_OUTPUT, "%s: send_cb -> %d", __func__, sent);
+		if (sent)
+			/* something sent or error */
+			return;
+
+		/* no command to send; get skb */
+		if (!(bcs->tx_skb = skb_dequeue(&bcs->squeue)))
+			/* no skb either, nothing to do */
+			return;
+
+		gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)",
+			(unsigned long) bcs->tx_skb);
+	}
+
+	/* send skb */
+	gig_dbg(DEBUG_OUTPUT, "%s: tx_skb", __func__);
+	if (write_modem(cs) < 0)
+		gig_dbg(DEBUG_OUTPUT, "%s: write_modem failed", __func__);
+}
+
+/*
+ * throw away all data queued for sending
+ */
+static void flush_send_queue(struct cardstate *cs)
+{
+	struct sk_buff *skb;
+	struct cmdbuf_t *cb;
+	unsigned long flags;
+
+	/* command queue */
+	spin_lock_irqsave(&cs->cmdlock, flags);
+	while ((cb = cs->cmdbuf) != NULL) {
+		cs->cmdbuf = cb->next;
+		if (cb->wake_tasklet)
+			tasklet_schedule(cb->wake_tasklet);
+		kfree(cb);
+	}
+	cs->cmdbuf = cs->lastcmdbuf = NULL;
+	cs->cmdbytes = cs->curlen = 0;
+	spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+	/* data queue */
+	if (cs->bcs->tx_skb)
+		dev_kfree_skb_any(cs->bcs->tx_skb);
+	while ((skb = skb_dequeue(&cs->bcs->squeue)) != NULL)
+		dev_kfree_skb_any(skb);
+}
+
+
+/* Gigaset Driver Interface */
+/* ======================== */
+
+/*
+ * queue an AT command string for transmission to the Gigaset device
+ * parameters:
+ *	cs		controller state structure
+ *	buf		buffer containing the string to send
+ *	len		number of characters to send
+ *	wake_tasklet	tasklet to run when transmission is complete, or NULL
+ * return value:
+ *	number of bytes queued, or error code < 0
+ */
+static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
+                             int len, struct tasklet_struct *wake_tasklet)
+{
+	struct cmdbuf_t *cb;
+	unsigned long flags;
+
+	gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
+	                     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
+	                   "CMD Transmit", len, buf);
+
+	if (len <= 0)
+		return 0;
+
+	if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
+		dev_err(cs->dev, "%s: out of memory!\n", __func__);
+		return -ENOMEM;
+	}
+
+	memcpy(cb->buf, buf, len);
+	cb->len = len;
+	cb->offset = 0;
+	cb->next = NULL;
+	cb->wake_tasklet = wake_tasklet;
+
+	spin_lock_irqsave(&cs->cmdlock, flags);
+	cb->prev = cs->lastcmdbuf;
+	if (cs->lastcmdbuf)
+		cs->lastcmdbuf->next = cb;
+	else {
+		cs->cmdbuf = cb;
+		cs->curlen = len;
+	}
+	cs->cmdbytes += len;
+	cs->lastcmdbuf = cb;
+	spin_unlock_irqrestore(&cs->cmdlock, flags);
+
+	spin_lock_irqsave(&cs->lock, flags);
+	if (cs->connected)
+		tasklet_schedule(&cs->write_tasklet);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	return len;
+}
+
+/*
+ * tty_driver.write_room interface routine
+ * return number of characters the driver will accept to be written
+ * parameter:
+ *	controller state structure
+ * return value:
+ *	number of characters
+ */
+static int gigaset_write_room(struct cardstate *cs)
+{
+	unsigned bytes;
+
+	bytes = cs->cmdbytes;
+	return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0;
+}
+
+/*
+ * tty_driver.chars_in_buffer interface routine
+ * return number of characters waiting to be sent
+ * parameter:
+ *	controller state structure
+ * return value:
+ *	number of characters
+ */
+static int gigaset_chars_in_buffer(struct cardstate *cs)
+{
+	return cs->cmdbytes;
+}
+
+/*
+ * implementation of ioctl(GIGASET_BRKCHARS)
+ * parameter:
+ *	controller state structure
+ * return value:
+ *	-EINVAL (unimplemented function)
+ */
+static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6])
+{
+	/* not implemented */
+	return -EINVAL;
+}
+
+/*
+ * Open B channel
+ * Called by "do_action" in ev-layer.c
+ */
+static int gigaset_init_bchannel(struct bc_state *bcs)
+{
+	/* nothing to do for M10x */
+	gigaset_bchannel_up(bcs);
+	return 0;
+}
+
+/*
+ * Close B channel
+ * Called by "do_action" in ev-layer.c
+ */
+static int gigaset_close_bchannel(struct bc_state *bcs)
+{
+	/* nothing to do for M10x */
+	gigaset_bchannel_down(bcs);
+	return 0;
+}
+
+/*
+ * Set up B channel structure
+ * This is called by "gigaset_initcs" in common.c
+ */
+static int gigaset_initbcshw(struct bc_state *bcs)
+{
+	/* unused */
+	bcs->hw.ser = NULL;
+	return 1;
+}
+
+/*
+ * Free B channel structure
+ * Called by "gigaset_freebcs" in common.c
+ */
+static int gigaset_freebcshw(struct bc_state *bcs)
+{
+	/* unused */
+	return 1;
+}
+
+/*
+ * Reinitialize B channel structure
+ * This is called by "bcs_reinit" in common.c
+ */
+static void gigaset_reinitbcshw(struct bc_state *bcs)
+{
+	/* nothing to do for M10x */
+}
+
+/*
+ * Free hardware specific device data
+ * This will be called by "gigaset_freecs" in common.c
+ */
+static void gigaset_freecshw(struct cardstate *cs)
+{
+	tasklet_kill(&cs->write_tasklet);
+	if (!cs->hw.ser)
+		return;
+	dev_set_drvdata(&cs->hw.ser->dev.dev, NULL);
+	platform_device_unregister(&cs->hw.ser->dev);
+	kfree(cs->hw.ser);
+	cs->hw.ser = NULL;
+}
+
+static void gigaset_device_release(struct device *dev)
+{
+	struct platform_device *pdev =
+		container_of(dev, struct platform_device, dev);
+
+	/* adapted from platform_device_release() in drivers/base/platform.c */
+	//FIXME is this actually necessary?
+	kfree(dev->platform_data);
+	kfree(pdev->resource);
+}
+
+/*
+ * Set up hardware specific device data
+ * This is called by "gigaset_initcs" in common.c
+ */
+static int gigaset_initcshw(struct cardstate *cs)
+{
+	int rc;
+
+	if (!(cs->hw.ser = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL))) {
+		err("%s: out of memory!", __func__);
+		return 0;
+	}
+
+	cs->hw.ser->dev.name = GIGASET_MODULENAME;
+	cs->hw.ser->dev.id = cs->minor_index;
+	cs->hw.ser->dev.dev.release = gigaset_device_release;
+	if ((rc = platform_device_register(&cs->hw.ser->dev)) != 0) {
+		err("error %d registering platform device", rc);
+		kfree(cs->hw.ser);
+		cs->hw.ser = NULL;
+		return 0;
+	}
+	dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
+
+	tasklet_init(&cs->write_tasklet,
+	             &gigaset_modem_fill, (unsigned long) cs);
+	return 1;
+}
+
+/*
+ * set modem control lines
+ * Parameters:
+ *	card state structure
+ *	modem control line state ([TIOCM_DTR]|[TIOCM_RTS])
+ * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c
+ * and by "if_lock" and "if_termios" in interface.c
+ */
+static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state)
+{
+	struct tty_struct *tty = cs->hw.ser->tty;
+	unsigned int set, clear;
+
+	if (!tty || !tty->driver || !tty->driver->tiocmset)
+		return -EFAULT;
+	set = new_state & ~old_state;
+	clear = old_state & ~new_state;
+	if (!set && !clear)
+		return 0;
+	gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
+	return tty->driver->tiocmset(tty, NULL, set, clear);
+}
+
+static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
+{
+	return -EINVAL;
+}
+
+static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
+{
+	return -EINVAL;
+}
+
+static struct gigaset_ops ops = {
+	gigaset_write_cmd,
+	gigaset_write_room,
+	gigaset_chars_in_buffer,
+	gigaset_brkchars,
+	gigaset_init_bchannel,
+	gigaset_close_bchannel,
+	gigaset_initbcshw,
+	gigaset_freebcshw,
+	gigaset_reinitbcshw,
+	gigaset_initcshw,
+	gigaset_freecshw,
+	gigaset_set_modem_ctrl,
+	gigaset_baud_rate,
+	gigaset_set_line_ctrl,
+	gigaset_m10x_send_skb,	/* asyncdata.c */
+	gigaset_m10x_input,	/* asyncdata.c */
+};
+
+
+/* Line Discipline Interface */
+/* ========================= */
+
+/* helper functions for cardstate refcounting */
+static struct cardstate *cs_get(struct tty_struct *tty)
+{
+	struct cardstate *cs = tty->disc_data;
+
+	if (!cs || !cs->hw.ser) {
+		gig_dbg(DEBUG_ANY, "%s: no cardstate", __func__);
+		return NULL;
+	}
+	atomic_inc(&cs->hw.ser->refcnt);
+	return cs;
+}
+
+static void cs_put(struct cardstate *cs)
+{
+	if (atomic_dec_and_test(&cs->hw.ser->refcnt))
+		mutex_unlock(&cs->hw.ser->dead_mutex);
+}
+
+/*
+ * Called by the tty driver when the line discipline is pushed onto the tty.
+ * Called in process context.
+ */
+static int
+gigaset_tty_open(struct tty_struct *tty)
+{
+	struct cardstate *cs;
+
+	gig_dbg(DEBUG_INIT, "Starting HLL for Gigaset M101");
+
+	info(DRIVER_AUTHOR);
+	info(DRIVER_DESC);
+
+	if (!driver) {
+		err("%s: no driver structure", __func__);
+		return -ENODEV;
+	}
+
+	/* allocate memory for our device state and intialize it */
+	if (!(cs = gigaset_initcs(driver, 1, 1, 0, cidmode,
+				  GIGASET_MODULENAME)))
+		goto error;
+
+	cs->dev = &cs->hw.ser->dev.dev;
+	cs->hw.ser->tty = tty;
+	mutex_init(&cs->hw.ser->dead_mutex);
+	atomic_set(&cs->hw.ser->refcnt, 1);
+
+	tty->disc_data = cs;
+
+	/* OK.. Initialization of the datastructures and the HW is done.. Now
+	 * startup system and notify the LL that we are ready to run
+	 */
+	if (startmode == SM_LOCKED)
+		atomic_set(&cs->mstate, MS_LOCKED);
+	if (!gigaset_start(cs)) {
+		tasklet_kill(&cs->write_tasklet);
+		goto error;
+	}
+
+	gig_dbg(DEBUG_INIT, "Startup of HLL done");
+	mutex_lock(&cs->hw.ser->dead_mutex);
+	return 0;
+
+error:
+	gig_dbg(DEBUG_INIT, "Startup of HLL failed");
+	tty->disc_data = NULL;
+	gigaset_freecs(cs);
+	return -ENODEV;
+}
+
+/*
+ * Called by the tty driver when the line discipline is removed.
+ * Called from process context.
+ */
+static void
+gigaset_tty_close(struct tty_struct *tty)
+{
+	struct cardstate *cs = tty->disc_data;
+
+	gig_dbg(DEBUG_INIT, "Stopping HLL for Gigaset M101");
+
+	if (!cs) {
+		gig_dbg(DEBUG_INIT, "%s: no cardstate", __func__);
+		return;
+	}
+
+	/* prevent other callers from entering ldisc methods */
+	tty->disc_data = NULL;
+
+	if (!cs->hw.ser)
+		err("%s: no hw cardstate", __func__);
+	else {
+		/* wait for running methods to finish */
+		if (!atomic_dec_and_test(&cs->hw.ser->refcnt))
+			mutex_lock(&cs->hw.ser->dead_mutex);
+	}
+
+	/* stop operations */
+	gigaset_stop(cs);
+	tasklet_kill(&cs->write_tasklet);
+	flush_send_queue(cs);
+	cs->dev = NULL;
+	gigaset_freecs(cs);
+
+	gig_dbg(DEBUG_INIT, "Shutdown of HLL done");
+}
+
+/*
+ * Called by the tty driver when the tty line is hung up.
+ * Wait for I/O to driver to complete and unregister ISDN device.
+ * This is already done by the close routine, so just call that.
+ * Called from process context.
+ */
+static int gigaset_tty_hangup(struct tty_struct *tty)
+{
+	gigaset_tty_close(tty);
+	return 0;
+}
+
+/*
+ * Read on the tty.
+ * Unused, received data goes only to the Gigaset driver.
+ */
+static ssize_t
+gigaset_tty_read(struct tty_struct *tty, struct file *file,
+		 unsigned char __user *buf, size_t count)
+{
+	return -EAGAIN;
+}
+
+/*
+ * Write on the tty.
+ * Unused, transmit data comes only from the Gigaset driver.
+ */
+static ssize_t
+gigaset_tty_write(struct tty_struct *tty, struct file *file,
+		  const unsigned char *buf, size_t count)
+{
+	return -EAGAIN;
+}
+
+/*
+ * Ioctl on the tty.
+ * Called in process context only.
+ * May be re-entered by multiple ioctl calling threads.
+ */
+static int
+gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,
+		  unsigned int cmd, unsigned long arg)
+{
+	struct cardstate *cs = cs_get(tty);
+	int rc, val;
+	int __user *p = (int __user *)arg;
+
+	if (!cs)
+		return -ENXIO;
+
+	switch (cmd) {
+	case TCGETS:
+	case TCGETA:
+		/* pass through to underlying serial device */
+		rc = n_tty_ioctl(tty, file, cmd, arg);
+		break;
+
+	case TCFLSH:
+		/* flush our buffers and the serial port's buffer */
+		switch (arg) {
+		case TCIFLUSH:
+			/* no own input buffer to flush */
+			break;
+		case TCIOFLUSH:
+		case TCOFLUSH:
+			flush_send_queue(cs);
+			break;
+		}
+		/* flush the serial port's buffer */
+		rc = n_tty_ioctl(tty, file, cmd, arg);
+		break;
+
+	case FIONREAD:
+		/* unused, always return zero */
+		val = 0;
+		rc = put_user(val, p);
+		break;
+
+	default:
+		rc = -ENOIOCTLCMD;
+	}
+
+	cs_put(cs);
+	return rc;
+}
+
+/*
+ * Poll on the tty.
+ * Unused, always return zero.
+ */
+static unsigned int
+gigaset_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
+{
+	return 0;
+}
+
+/*
+ * Called by the tty driver when a block of data has been received.
+ * Will not be re-entered while running but other ldisc functions
+ * may be called in parallel.
+ * Can be called from hard interrupt level as well as soft interrupt
+ * level or mainline.
+ * Parameters:
+ *	tty	tty structure
+ *	buf	buffer containing received characters
+ *	cflags	buffer containing error flags for received characters (ignored)
+ *	count	number of received characters
+ */
+static void
+gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
+		    char *cflags, int count)
+{
+	struct cardstate *cs = cs_get(tty);
+	unsigned tail, head, n;
+	struct inbuf_t *inbuf;
+
+	if (!cs)
+		return;
+	if (!(inbuf = cs->inbuf)) {
+		dev_err(cs->dev, "%s: no inbuf\n", __func__);
+		cs_put(cs);
+		return;
+	}
+
+	tail = atomic_read(&inbuf->tail);
+	head = atomic_read(&inbuf->head);
+	gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes",
+		head, tail, count);
+
+	if (head <= tail) {
+		/* possible buffer wraparound */
+		n = min_t(unsigned, count, RBUFSIZE - tail);
+		memcpy(inbuf->data + tail, buf, n);
+		tail = (tail + n) % RBUFSIZE;
+		buf += n;
+		count -= n;
+	}
+
+	if (count > 0) {
+		/* tail < head and some data left */
+		n = head - tail - 1;
+		if (count > n) {
+			dev_err(cs->dev,
+				"inbuf overflow, discarding %d bytes\n",
+				count - n);
+			count = n;
+		}
+		memcpy(inbuf->data + tail, buf, count);
+		tail += count;
+	}
+
+	gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
+	atomic_set(&inbuf->tail, tail);
+
+	/* Everything was received .. Push data into handler */
+	gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
+	gigaset_schedule_event(cs);
+	cs_put(cs);
+}
+
+/*
+ * Called by the tty driver when there's room for more data to send.
+ */
+static void
+gigaset_tty_wakeup(struct tty_struct *tty)
+{
+	struct cardstate *cs = cs_get(tty);
+
+	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+	if (!cs)
+		return;
+	tasklet_schedule(&cs->write_tasklet);
+	cs_put(cs);
+}
+
+static struct tty_ldisc gigaset_ldisc = {
+	.owner		= THIS_MODULE,
+	.magic		= TTY_LDISC_MAGIC,
+	.name		= "ser_gigaset",
+	.open		= gigaset_tty_open,
+	.close		= gigaset_tty_close,
+	.hangup		= gigaset_tty_hangup,
+	.read		= gigaset_tty_read,
+	.write		= gigaset_tty_write,
+	.ioctl		= gigaset_tty_ioctl,
+	.poll		= gigaset_tty_poll,
+	.receive_buf	= gigaset_tty_receive,
+	.write_wakeup	= gigaset_tty_wakeup,
+};
+
+
+/* Initialization / Shutdown */
+/* ========================= */
+
+static int __init ser_gigaset_init(void)
+{
+	int rc;
+
+	gig_dbg(DEBUG_INIT, "%s", __func__);
+	if ((rc = platform_driver_register(&device_driver)) != 0) {
+		err("error %d registering platform driver", rc);
+		return rc;
+	}
+
+	/* allocate memory for our driver state and intialize it */
+	if (!(driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
+					  GIGASET_MODULENAME, GIGASET_DEVNAME,
+					  &ops, THIS_MODULE)))
+		goto error;
+
+	if ((rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc)) != 0) {
+		err("error %d registering line discipline", rc);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	if (driver) {
+		gigaset_freedriver(driver);
+		driver = NULL;
+	}
+	platform_driver_unregister(&device_driver);
+	return rc;
+}
+
+static void __exit ser_gigaset_exit(void)
+{
+	int rc;
+
+	gig_dbg(DEBUG_INIT, "%s", __func__);
+
+	if (driver) {
+		gigaset_freedriver(driver);
+		driver = NULL;
+	}
+
+	if ((rc = tty_unregister_ldisc(N_GIGASET_M101)) != 0)
+		err("error %d unregistering line discipline", rc);
+
+	platform_driver_unregister(&device_driver);
+}
+
+module_init(ser_gigaset_init);
+module_exit(ser_gigaset_exit);
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index ddd47cd..1e2d38e 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -29,7 +29,7 @@
 
 static char *revision = "$Revision: 1.1.2.3 $";
 
-#undef CONFIG_B1DMA_DEBUG
+#undef AVM_B1DMA_DEBUG
 
 /* ------------------------------------------------------------- */
 
@@ -391,16 +391,16 @@
 			_put_slice(&p, skb->data, len);
 		}
 		txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
-#ifdef CONFIG_B1DMA_DEBUG
+#ifdef AVM_B1DMA_DEBUG
 		printk(KERN_DEBUG "tx: put msg len=%d\n", txlen);
 #endif
 	} else {
 		txlen = skb->len-2;
-#ifdef CONFIG_B1DMA_POLLDEBUG
+#ifdef AVM_B1DMA_POLLDEBUG
 		if (skb->data[2] == SEND_POLLACK)
 			printk(KERN_INFO "%s: send ack\n", card->name);
 #endif
-#ifdef CONFIG_B1DMA_DEBUG
+#ifdef AVM_B1DMA_DEBUG
 		printk(KERN_DEBUG "tx: put 0x%x len=%d\n", 
 		       skb->data[2], txlen);
 #endif
@@ -450,7 +450,7 @@
 	u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
 	u8 b1cmd =  _get_byte(&p);
 
-#ifdef CONFIG_B1DMA_DEBUG
+#ifdef AVM_B1DMA_DEBUG
 	printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen);
 #endif
 	
@@ -515,7 +515,7 @@
 		break;
 
 	case RECEIVE_START:
-#ifdef CONFIG_B1DMA_POLLDEBUG
+#ifdef AVM_B1DMA_POLLDEBUG
 		printk(KERN_INFO "%s: receive poll\n", card->name);
 #endif
 		if (!suppress_pollack)
@@ -601,7 +601,7 @@
 				rxlen = (dma->recvlen + 3) & ~3;
 				b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR);
 				b1dma_writel(card, rxlen, AMCC_RXLEN);
-#ifdef CONFIG_B1DMA_DEBUG
+#ifdef AVM_B1DMA_DEBUG
 			} else {
 				printk(KERN_ERR "%s: rx not complete (%d).\n",
 					card->name, rxlen);
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 2a3eb38..6f5efa8d 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -28,8 +28,8 @@
 #include <linux/isdn/capilli.h>
 #include "avmcard.h"
 
-#undef CONFIG_C4_DEBUG
-#undef CONFIG_C4_POLLDEBUG
+#undef AVM_C4_DEBUG
+#undef AVM_C4_POLLDEBUG
 
 /* ------------------------------------------------------------- */
 
@@ -420,7 +420,7 @@
 
 	skb = skb_dequeue(&dma->send_queue);
 	if (!skb) {
-#ifdef CONFIG_C4_DEBUG
+#ifdef AVM_C4_DEBUG
 		printk(KERN_DEBUG "%s: tx underrun\n", card->name);
 #endif
 		return;
@@ -444,16 +444,16 @@
 			_put_slice(&p, skb->data, len);
 		}
 		txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf;
-#ifdef CONFIG_C4_DEBUG
+#ifdef AVM_C4_DEBUG
 		printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen);
 #endif
 	} else {
 		txlen = skb->len-2;
-#ifdef CONFIG_C4_POLLDEBUG
+#ifdef AVM_C4_POLLDEBUG
 		if (skb->data[2] == SEND_POLLACK)
 			printk(KERN_INFO "%s: ack to c4\n", card->name);
 #endif
-#ifdef CONFIG_C4_DEBUG
+#ifdef AVM_C4_DEBUG
 		printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n",
 				card->name, skb->data[2], txlen);
 #endif
@@ -508,7 +508,7 @@
 	u32 cidx;
 
 
-#ifdef CONFIG_C4_DEBUG
+#ifdef AVM_C4_DEBUG
 	printk(KERN_DEBUG "%s: rx 0x%x len=%lu\n", card->name,
 				b1cmd, (unsigned long)dma->recvlen);
 #endif
@@ -586,7 +586,7 @@
 		break;
 
 	case RECEIVE_START:
-#ifdef CONFIG_C4_POLLDEBUG
+#ifdef AVM_C4_POLLDEBUG
 		printk(KERN_INFO "%s: poll from c4\n", card->name);
 #endif
 		if (!suppress_pollack)
diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
index 0afd763..ff284ae 100644
--- a/drivers/isdn/hardware/eicon/capifunc.c
+++ b/drivers/isdn/hardware/eicon/capifunc.c
@@ -187,7 +187,7 @@
  */
 void *TransmitBufferSet(APPL * appl, dword ref)
 {
-	appl->xbuffer_used[ref] = TRUE;
+	appl->xbuffer_used[ref] = true;
 	DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1))
 	    return (void *) ref;
 }
@@ -202,7 +202,7 @@
 
 void TransmitBufferFree(APPL * appl, void *p)
 {
-	appl->xbuffer_used[(dword) p] = FALSE;
+	appl->xbuffer_used[(dword) p] = false;
 	DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword) p) + 1))
 }
 
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
index d835e74..0db9cc6 100644
--- a/drivers/isdn/hardware/eicon/debug.c
+++ b/drivers/isdn/hardware/eicon/debug.c
@@ -287,7 +287,7 @@
   }
   external_dbg_queue = 0;
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].pmem) {
       diva_os_free (0, clients[i].pmem);
     }
@@ -391,7 +391,7 @@
 
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
 
-  for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
+  for (id = 1; id < ARRAY_SIZE(clients); id++) {
     if (clients[id].hDbg == hDbg) {
       /*
         driver already registered
@@ -494,7 +494,7 @@
   diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg == hDbg) {
       diva_dbg_entry_head_t* pmsg;
       char tmp[256];
@@ -736,7 +736,7 @@
   int to_copy;
 
   if (!data || !id || (data_length < 17) ||
-      (id >= (sizeof(clients)/sizeof(clients[0])))) {
+      (id >= ARRAY_SIZE(clients))) {
     return (-1);
   }
 
@@ -786,7 +786,7 @@
   diva_os_spin_lock_magic_t old_irql;
   int ret = -1;
 
-  if (!data || !id || (id >= (sizeof(clients)/sizeof(clients[0])))) {
+  if (!data || !id || (id >= ARRAY_SIZE(clients))) {
     return (-1);
   }
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info");
@@ -809,7 +809,7 @@
   int ret = -1;
   
 
-  if (!id || (id >= (sizeof(clients)/sizeof(clients[0])))) {
+  if (!id || (id >= ARRAY_SIZE(clients))) {
     return (-1);
   }
 
@@ -887,7 +887,7 @@
   diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
 
-  for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
+  for (id = 1; id < ARRAY_SIZE(clients); id++) {
     if (clients[id].hDbg && (clients[id].request == d->request)) {
       diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
       diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
@@ -1037,7 +1037,7 @@
   diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
   diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg && (clients[i].request == d->request)) {
       diva_dbg_entry_head_t* pmsg;
       char tmp[256];
@@ -1115,7 +1115,7 @@
 void* SuperTraceOpenAdapter   (int AdapterNumber) {
   int i;
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg && clients[i].request && (clients[i].logical == AdapterNumber)) {
       return (&clients[i]);
     }
@@ -1508,7 +1508,7 @@
 					int ch = TraceFilterChannel;
 					int id = TraceFilterIdent;
 
-					if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+					if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
 						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
 						if (ch != (int)modem->ChannelNumber) {
 							break;
@@ -1555,7 +1555,7 @@
 					int ch = TraceFilterChannel;
 					int id = TraceFilterIdent;
 
-					if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+					if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
 						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
 						if (ch != (int)fax->ChannelNumber) {
 							break;
@@ -1803,7 +1803,7 @@
   /*
     Selective trace
     */
-  if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+  if ((id >= 0) && (ch >= 0) && (id < ARRAY_SIZE(clients)) &&
       (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
     const char* p = NULL;
     int ch_value = -1;
@@ -1925,7 +1925,7 @@
   byte * pmem;
 
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     pmem = NULL;
 
     diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
@@ -2006,7 +2006,7 @@
 
   on = (TraceFilter[0] == 0);
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
       client_b_on    = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
       client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO)    != 0);
@@ -2017,7 +2017,7 @@
     }
   }
 
-  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+  for (i = 1; i < ARRAY_SIZE(clients); i++) {
     if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
       diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
       clients[i].request_pending = 0;
diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c
index e1df8d9..ce8df38 100644
--- a/drivers/isdn/hardware/eicon/di.c
+++ b/drivers/isdn/hardware/eicon/di.c
@@ -173,16 +173,16 @@
         xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->MInd,
                           a->IdTypeTable[this->No]);
         a->ram_out(a, &ReqOut->Req, this->MInd);
-        more = TRUE;
+        more = true;
       }
       else {
         xdi_xlog_request (XDI_A_NR(a), this->Id, this->ReqCh, this->Req,
                           a->IdTypeTable[this->No]);
         this->More |=XMOREF;
         a->ram_out(a, &ReqOut->Req, this->Req);
-        more = FALSE;
+        more = false;
         if (a->FlowControlIdTable[this->ReqCh] == this->Id)
-          a->FlowControlSkipTable[this->ReqCh] = TRUE;
+          a->FlowControlSkipTable[this->ReqCh] = true;
         /*
            Note that remove request was sent to the card
            */
@@ -311,7 +311,7 @@
         /* are marked RNR                                           */
       if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) {
         a->ram_out(a, &IndIn->Ind, 0);
-        a->ram_out(a, &IndIn->RNR, TRUE);
+        a->ram_out(a, &IndIn->RNR, true);
       }
       else {
         Ind = a->ram_in(a, &IndIn->Ind);
@@ -331,7 +331,7 @@
             dtrc(dprintf("RNR"));
             a->ram_out(a, &IndIn->Ind, 0);
             RNRId = a->ram_in(a, &IndIn->IndId);
-            a->ram_out(a, &IndIn->RNR, TRUE);
+            a->ram_out(a, &IndIn->RNR, true);
           }
         }
       }
@@ -340,7 +340,7 @@
     }
     a->ram_out(a, &PR_RAM->IndOutput, 0);
   }
-  return FALSE;
+  return false;
 }
 byte scom_test_int(ADAPTER * a)
 {
@@ -399,7 +399,7 @@
           return (0);
         }
         if (extended_info_type == DIVA_RC_TYPE_REMOVE_COMPLETE)
-          a->RcExtensionSupported = TRUE;
+          a->RcExtensionSupported = true;
       }
       a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_REMOVE_PENDING;
       a->misc_flags_table[e_no] &= ~DIVA_MISC_FLAGS_NO_RC_CANCELLING;
@@ -428,7 +428,7 @@
     }
     if (Rc==OK_FC) {
       a->FlowControlIdTable[Ch] = Id;
-      a->FlowControlSkipTable[Ch] = FALSE;
+      a->FlowControlSkipTable[Ch] = false;
       this->Rc = Rc;
       this->More &= ~(XBUSY | XMOREC);
       this->complete=0xff;
diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
index 77155d9..6b2940e 100644
--- a/drivers/isdn/hardware/eicon/divamnt.c
+++ b/drivers/isdn/hardware/eicon/divamnt.c
@@ -164,7 +164,7 @@
 	return (maint_read_write(buf, (int) count));
 }
 
-static struct file_operations divas_maint_fops = {
+static const struct file_operations divas_maint_fops = {
 	.owner   = THIS_MODULE,
 	.llseek  = no_llseek,
 	.read    = divas_maint_read,
diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c
index fff0d89..556b196 100644
--- a/drivers/isdn/hardware/eicon/divasi.c
+++ b/drivers/isdn/hardware/eicon/divasi.c
@@ -131,7 +131,7 @@
 	}
 }
 
-static struct file_operations divas_idi_fops = {
+static const struct file_operations divas_idi_fops = {
 	.owner   = THIS_MODULE,
 	.llseek  = no_llseek,
 	.read    = um_idi_read,
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index 91fc92c..b365e44 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -663,7 +663,7 @@
 	return (POLLIN | POLLRDNORM);
 }
 
-static struct file_operations divas_fops = {
+static const struct file_operations divas_fops = {
 	.owner   = THIS_MODULE,
 	.llseek  = no_llseek,
 	.read    = divas_read,
diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c
index 6a4373a..0632a26 100644
--- a/drivers/isdn/hardware/eicon/divasproc.c
+++ b/drivers/isdn/hardware/eicon/divasproc.c
@@ -113,7 +113,7 @@
 	return (0);
 }
 
-static struct file_operations divas_fops = {
+static const struct file_operations divas_fops = {
 	.owner   = THIS_MODULE,
 	.llseek  = no_llseek,
 	.read    = divas_read,
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
index f9b00f1..784232a 100644
--- a/drivers/isdn/hardware/eicon/message.c
+++ b/drivers/isdn/hardware/eicon/message.c
@@ -253,7 +253,7 @@
 
 
 
-static byte remove_started = FALSE;
+static byte remove_started = false;
 static PLCI dummy_plci;
 
 
@@ -456,12 +456,12 @@
 
         return _QUEUE_FULL;
       }
-      c = FALSE;
+      c = false;
       if ((((byte   *) msg) < ((byte   *)(plci->msg_in_queue)))
        || (((byte   *) msg) >= ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
       {
         if (plci->msg_in_write_pos != plci->msg_in_read_pos)
-          c = TRUE;
+          c = true;
       }
       if (msg->header.command == _DATA_B3_R)
       {
@@ -506,13 +506,13 @@
 
             return _QUEUE_FULL;
           }
-          c = TRUE;
+          c = true;
         }
       }
       else
       {
         if (plci->req_in || plci->internal_command)
-          c = TRUE;
+          c = true;
         else
         {
           plci->command = msg->header.command;
@@ -626,10 +626,10 @@
       break;
     }
 
-    if(p>length) return TRUE;
+    if(p>length) return true;
   }
   if(parms) parms[i].info = NULL;
-  return FALSE;
+  return false;
 }
 
 void api_save_msg(API_PARSE   *in, byte *format, API_SAVE   *out)
@@ -687,7 +687,7 @@
   word j;
 
   if(!remove_started) {
-    remove_started = TRUE;
+    remove_started = true;
     for(i=0;i<max_adapter;i++) {
       if(adapter[i].request) {
         for(j=0;j<adapter[i].max_plci;j++) {
@@ -1080,7 +1080,7 @@
       send_req(plci);
     }
   }
-  ncci_remove (plci, 0, FALSE);
+  ncci_remove (plci, 0, false);
   plci_free_msg_in_queue (plci);
 
   plci->channels = 0;
@@ -1226,7 +1226,7 @@
       Id = ((word)1<<8)|a->Id;
       sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
       sendf(appl, _DISCONNECT_I, Id, 0, "w", _L1_ERROR);
-      return FALSE;
+      return false;
     }
     Info = _OUT_OF_PLCI;
     if((i=get_plci(a)))
@@ -1330,7 +1330,7 @@
       plci->command = _CONNECT_R;
       plci->number = Number;
       /* x.31 or D-ch free SAPI in LinkLayer? */
-      if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = TRUE;
+      if(ch==1 && LinkLayer!=3 && LinkLayer!=12) noCh = true;
       if((ch==0 || ch==2 || noCh || ch==3 || ch==4) && !Info)
       {
         /* B-channel used for B3 connections (ch==0), or no B channel    */
@@ -1381,7 +1381,7 @@
             plci->command = 0;
             dbug(1,dprintf("Spoof"));
             send_req(plci);
-            return FALSE;
+            return false;
           }
           if(ch==4)add_p(plci,CHI,p_chi);
           add_s(plci,CPN,&parms[1]);
@@ -1395,11 +1395,11 @@
             plci->appl = appl;
             sig_req(plci,LISTEN_REQ,0);
             send_req(plci);
-            return FALSE;
+            return false;
           }
         }
         send_req(plci);
-        return FALSE;
+        return false;
       }
       plci->Id = 0;
     }
@@ -1571,7 +1571,7 @@
 byte connect_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 {
   dbug(1,dprintf("connect_a_res"));
-  return FALSE;
+  return false;
 }
 
 byte disconnect_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
@@ -1624,9 +1624,9 @@
       }
     }
 
-  if(!appl)  return FALSE;
+  if(!appl)  return false;
   sendf(appl, _DISCONNECT_R|CONFIRM, Id, Number, "w",Info);
-  return FALSE;
+  return false;
 }
 
 byte disconnect_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
@@ -1702,7 +1702,7 @@
         "w",Info);
 
   if (a) listen_check(a);
-  return FALSE;
+  return false;
 }
 
 byte info_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
@@ -1739,7 +1739,7 @@
       add_s(plci,KEY,&ai_parms[1]);
       sig_req(plci,INFO_REQ,0);
       send_req(plci);
-      return FALSE;
+      return false;
     }
 
     if(plci->State && ai_parms[2].length)
@@ -1769,7 +1769,7 @@
     if((i=get_plci(a)))
     {
       rc_plci = &a->plci[i-1];
-      appl->NullCREnable  = TRUE;
+      appl->NullCREnable  = true;
       rc_plci->internal_command = C_NCR_FAC_REQ;
       rc_plci->appl = appl;
       add_p(rc_plci,CAI,"\x01\x80");
@@ -1788,7 +1788,7 @@
       add_ai(rc_plci, &msg[1]);
       sig_req(rc_plci,NCR_FACILITY,0);
       send_req(rc_plci);
-      return FALSE;
+      return false;
      /* for application controlled supplementary services    */
     }
   }
@@ -1811,13 +1811,13 @@
           Number,
           "w",Info);
   }
-  return FALSE;
+  return false;
 }
 
 byte info_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 {
   dbug(1,dprintf("info_res"));
-  return FALSE;
+  return false;
 }
 
 byte alert_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
@@ -1828,7 +1828,7 @@
   dbug(1,dprintf("alert_req"));
 
   Info = _WRONG_IDENTIFIER;
-  ret = FALSE;
+  ret = false;
   if(plci) {
     Info = _ALERT_IGNORED;
     if(plci->State!=INC_CON_ALERT) {
@@ -1922,7 +1922,7 @@
             rplci->appl = appl;
             sig_req(rplci,S_SUPPORTED,0);
             send_req(rplci);
-            return FALSE;
+            return false;
             break;
 
           case S_LISTEN:
@@ -1972,7 +1972,7 @@
               add_s(plci,CAI,&ss_parms[1]);
               sig_req(plci,CALL_HOLD,0);
               send_req(plci);
-              return FALSE;
+              return false;
             }
             else Info = 0x3010;                    /* wrong state           */
             break;
@@ -1997,13 +1997,13 @@
                 plci->internal_command = BLOCK_PLCI;
                 plci->command = 0;
                 dbug(1,dprintf("Spoof"));
-                return FALSE;
+                return false;
               }
               else
               {
                 sig_req(plci,CALL_RETRIEVE,0);
                 send_req(plci);
-                return FALSE;
+                return false;
               }
             }
             else Info = 0x3010;                    /* wrong state           */
@@ -2123,7 +2123,7 @@
               add_p(plci,CAI,cai);
               sig_req(plci,S_SERVICE,0);
               send_req(plci);
-              return FALSE;
+              return false;
             }
             else Info = 0x3010;                    /* wrong state           */
             break;
@@ -2265,7 +2265,7 @@
               add_p(rplci,CAI,cai);
               sig_req(rplci,S_SERVICE,0);
               send_req(rplci);
-              return FALSE;
+              return false;
             }
             else
             {
@@ -2291,14 +2291,14 @@
             ss_parms[3].info[3] = (byte)GET_WORD(&(ss_parms[2].info[0]));
             plci->command = 0;
             plci->internal_command = CD_REQ_PEND;
-            appl->CDEnable = TRUE;
+            appl->CDEnable = true;
             cai[0] = 1;
             cai[1] = CALL_DEFLECTION;
             add_p(plci,CAI,cai);
             add_p(plci,CPN,ss_parms[3].info);
             sig_req(plci,S_SERVICE,0);
             send_req(plci);
-            return FALSE;
+            return false;
             break;
 
           case S_CALL_FORWARDING_START:
@@ -2337,7 +2337,7 @@
             add_p(rplci,CPN,ss_parms[6].info);
             sig_req(rplci,S_SERVICE,0);
             send_req(rplci);
-            return FALSE;
+            return false;
             break;
 
           case S_INTERROGATE_DIVERSION:
@@ -2456,7 +2456,7 @@
                         
             sig_req(rplci,S_SERVICE,0);
             send_req(rplci);
-            return FALSE;
+            return false;
             break;
 
           case S_MWI_ACTIVATE:
@@ -2472,7 +2472,7 @@
               {
                 rplci = &a->plci[i-1];
                 rplci->appl = appl;
-                rplci->cr_enquiry=TRUE;
+                rplci->cr_enquiry=true;
                 add_p(rplci,CAI,"\x01\x80");
                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
                 sig_req(rplci,ASSIGN,DSIG_ID);
@@ -2487,7 +2487,7 @@
             else
             {
               rplci = plci;
-              rplci->cr_enquiry=FALSE;
+              rplci->cr_enquiry=false;
             }
 
             rplci->command = 0;
@@ -2509,7 +2509,7 @@
             add_p(rplci,UID,ss_parms[10].info); /* Time */
             sig_req(rplci,S_SERVICE,0);
             send_req(rplci);
-            return FALSE;
+            return false;
 
           case S_MWI_DEACTIVATE:
             if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
@@ -2524,7 +2524,7 @@
               {
                 rplci = &a->plci[i-1];
                 rplci->appl = appl;
-                rplci->cr_enquiry=TRUE;
+                rplci->cr_enquiry=true;
                 add_p(rplci,CAI,"\x01\x80");
                 add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
                 sig_req(rplci,ASSIGN,DSIG_ID);
@@ -2539,7 +2539,7 @@
             else
             {
               rplci = plci;
-              rplci->cr_enquiry=FALSE;
+              rplci->cr_enquiry=false;
             }
 
             rplci->command = 0;
@@ -2556,7 +2556,7 @@
             add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
             sig_req(rplci,S_SERVICE,0);
             send_req(rplci);
-            return FALSE;
+            return false;
 
           default:
             Info = 0x300E;  /* not supported */
@@ -2597,13 +2597,13 @@
         Id,
         Number,
         "wws",Info,selector,SSparms);
-  return FALSE;
+  return false;
 }
 
 byte facility_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * msg)
 {
   dbug(1,dprintf("facility_res"));
-  return FALSE;
+  return false;
 }
 
 byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -2649,7 +2649,7 @@
               Id,
               Number,
               "w",Info);
-        return FALSE;
+        return false;
       }
       plci->requested_options_conn = 0;
 
@@ -2684,7 +2684,7 @@
            || (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS))
           {
             len = (byte)(&(((T30_INFO *) 0)->universal_6));
-            fax_info_change = FALSE;
+            fax_info_change = false;
             if (ncpi->length >= 4)
             {
               w = GET_WORD(&ncpi->info[3]);
@@ -2693,7 +2693,7 @@
                 ((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution =
                   (byte)((((T30_INFO   *)(plci->fax_connect_info_buffer))->resolution & ~T30_RESOLUTION_R8_0770_OR_200) |
                   ((w & 0x0001) ? T30_RESOLUTION_R8_0770_OR_200 : 0));
-                fax_info_change = TRUE;
+                fax_info_change = true;
               }
               fax_control_bits &= ~(T30_CONTROL_BIT_REQUEST_POLLING | T30_CONTROL_BIT_MORE_DOCUMENTS);
               if (w & 0x0002)  /* Fax-polling request */
@@ -2709,7 +2709,7 @@
                 if (((byte) w) != ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format)
                 {
                   ((T30_INFO   *)(plci->fax_connect_info_buffer))->data_format = (byte) w;
-                  fax_info_change = TRUE;
+                  fax_info_change = true;
                 }
 
                 if ((a->man_profile.private_options & (1L << PRIVATE_FAX_SUB_SEP_PWD))
@@ -2781,13 +2781,13 @@
                 {
                   len = (byte)(&(((T30_INFO *) 0)->universal_6));
                 }
-                fax_info_change = TRUE;
+                fax_info_change = true;
 
               }
               if (fax_control_bits != GET_WORD(&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low))
               {
                 PUT_WORD (&((T30_INFO   *)plci->fax_connect_info_buffer)->control_bits_low, fax_control_bits);
-                fax_info_change = TRUE;
+                fax_info_change = true;
               }
             }
             if (Info == GOOD)
@@ -2798,12 +2798,12 @@
                 if (fax_feature_bits & T30_FEATURE_BIT_MORE_DOCUMENTS)
                 {
                   start_internal_command (Id, plci, fax_connect_info_command);
-                  return FALSE;
+                  return false;
                 }
                 else
                 {
                   start_internal_command (Id, plci, fax_adjust_b23_command);
-                  return FALSE;
+                  return false;
                 }
               }
             }
@@ -2820,7 +2820,7 @@
         for (w = 0; w < ncpi->length; w++)
           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
         start_internal_command (Id, plci, rtp_connect_b3_req_command);
-        return FALSE;
+        return false;
       }
 
       if(!Info)
@@ -2837,7 +2837,7 @@
         Id,
         Number,
         "w",Info);
-  return FALSE;
+  return false;
 }
 
 byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -2909,7 +2909,7 @@
             plci->fax_connect_info_length = len;
             ((T30_INFO *)(plci->fax_connect_info_buffer))->code = 0;
             start_internal_command (Id, plci, fax_connect_ack_command);
-     return FALSE;
+     return false;
           }
         }
 
@@ -2932,7 +2932,7 @@
         for (w = 0; w < ncpi->length; w++)
           plci->internal_req_buffer[2+w] = ncpi->info[1+w];
         start_internal_command (Id, plci, rtp_connect_b3_res_command);
-        return FALSE;
+        return false;
       }
 
       else
@@ -2945,14 +2945,14 @@
         sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
         if (plci->adjust_b_restore)
         {
-          plci->adjust_b_restore = FALSE;
+          plci->adjust_b_restore = false;
           start_internal_command (Id, plci, adjust_b_restore);
         }
       }
       return 1;
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte connect_b3_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -2972,7 +2972,7 @@
       channel_xmit_xon (plci);
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte disconnect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3004,7 +3004,7 @@
       {
         plci->send_disc = (byte)ncci;
         plci->command = 0;
-        return FALSE;
+        return false;
       }
       else
       {
@@ -3028,7 +3028,7 @@
         Id,
         Number,
         "w",Info);
-  return FALSE;
+  return false;
 }
 
 byte disconnect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3084,7 +3084,7 @@
       }
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3140,7 +3140,7 @@
       }
 
       send_data(plci);
-      return FALSE;
+      return false;
     }
   }
   if (appl)
@@ -3161,7 +3161,7 @@
           Number,
           "ww",GET_WORD(parms[2].info),Info);
   }
-  return FALSE;
+  return false;
 }
 
 byte data_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3194,7 +3194,7 @@
       }
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte reset_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3235,7 +3235,7 @@
         Id,
         Number,
         "w",Info);
-  return FALSE;
+  return false;
 }
 
 byte reset_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3254,12 +3254,12 @@
       {
         a->ncci_state[ncci] = CONNECTED;
         nl_req_ncci(plci,N_RESET_ACK,(byte)ncci);
-        return TRUE;
+        return true;
       }
     break;
     }
   }
-  return FALSE;
+  return false;
 }
 
 byte connect_b3_t90_a_res(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3292,7 +3292,7 @@
       return 1;
     }
   }
-  return FALSE;
+  return false;
 }
 
 
@@ -3378,7 +3378,7 @@
               plci->internal_command = BLOCK_PLCI; /* lock other commands */
               plci->command = 0;
               dbug(1,dprintf("continue if codec loaded"));
-              return FALSE;
+              return false;
             }
           }
         }
@@ -3407,12 +3407,12 @@
         else if (plci->call_dir & CALL_DIR_IN)
           plci->call_dir = CALL_DIR_IN | CALL_DIR_ANSWER;
         start_internal_command (Id, plci, select_b_command);
-        return FALSE;
+        return false;
       }
     }
   }
   sendf(appl, _SELECT_B_REQ|CONFIRM, Id, Number, "w", Info);
-  return FALSE;
+  return false;
 }
 
 byte manufacturer_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci, APPL   * appl, API_PARSE * parms)
@@ -3489,7 +3489,7 @@
           }
 
           plci->State = LOCAL_CONNECT;
-          plci->manufacturer = TRUE;
+          plci->manufacturer = true;
           plci->command = _MANUFACTURER_R;
           plci->m_command = command;
           plci->number = Number;
@@ -3520,7 +3520,7 @@
                 plci->internal_command = BLOCK_PLCI; /* reject other req meanwhile */
                 plci->command = 0;
                 send_req(plci);
-                return FALSE;
+                return false;
               }
               if(dir==1) {
                 sig_req(plci,CALL_REQ,0);
@@ -3573,7 +3573,7 @@
       }
       else if(req==LAW_REQ)
       {
-        plci->cr_enquiry = TRUE;
+        plci->cr_enquiry = true;
       }
       add_ss(plci,FTY,&m_parms[1]);
       sig_req(plci,req,0);
@@ -3739,7 +3739,7 @@
         Id,
         Number,
         "dww",_DI_MANU_ID,command,Info);
-  return FALSE;
+  return false;
 }
 
 
@@ -3760,7 +3760,7 @@
    || (msg[1].length == 0)
    || (GET_DWORD(msg[0].info)!=_DI_MANU_ID))
   {
-    return FALSE;
+    return false;
   }
   indication = GET_WORD(msg[1].info);
   switch (indication)
@@ -3811,7 +3811,7 @@
     break;
 
   }
-  return FALSE;
+  return false;
 }
 
 /*------------------------------------------------------------------*/
@@ -3908,14 +3908,14 @@
           plci->nl_req = 0;
       }
       if (plci->nl_req)
-        control_rc (plci, 0, rc, ch, 0, TRUE);
+        control_rc (plci, 0, rc, ch, 0, true);
       else
       {
         if (req == N_XON)
         {
           channel_x_on (plci, ch);
           if (plci->internal_command)
-            control_rc (plci, req, rc, ch, 0, TRUE);
+            control_rc (plci, req, rc, ch, 0, true);
         }
         else
         {
@@ -3931,21 +3931,21 @@
               }
             }
             channel_xmit_xon (plci);
-            control_rc (plci, 0, rc, ch, global_req, TRUE);
+            control_rc (plci, 0, rc, ch, global_req, true);
           }
           else if (plci->data_sent)
           {
             channel_xmit_xon (plci);
-            plci->data_sent = FALSE;
+            plci->data_sent = false;
             plci->NL.XNum = 1;
             data_rc (plci, ch);
             if (plci->internal_command)
-              control_rc (plci, req, rc, ch, 0, TRUE);
+              control_rc (plci, req, rc, ch, 0, true);
           }
           else
           {
             channel_xmit_xon (plci);
-            control_rc (plci, req, rc, ch, 0, TRUE);
+            control_rc (plci, req, rc, ch, 0, true);
           }
         }
       }
@@ -3974,12 +3974,12 @@
         if (rc != ASSIGN_OK)
           e->Id = 0;
         channel_xmit_xon (plci);
-        control_rc (plci, 0, rc, ch, global_req, FALSE);
+        control_rc (plci, 0, rc, ch, global_req, false);
       }
       else
       {
         channel_xmit_xon (plci);
-        control_rc (plci, req, rc, ch, 0, FALSE);
+        control_rc (plci, req, rc, ch, 0, false);
       }
     }
     /*
@@ -4065,8 +4065,8 @@
 
     if (plci->li_notify_update)
     {
-      plci->li_notify_update = FALSE;
-      mixer_notify_update (plci, FALSE);
+      plci->li_notify_update = false;
+      mixer_notify_update (plci, false);
     }
 
   }
@@ -4428,7 +4428,7 @@
           else
           {
             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
-            appl->NullCREnable = FALSE;
+            appl->NullCREnable = false;
             plci_remove(plci);
           }
         }
@@ -4441,7 +4441,7 @@
           else
           {
             sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
-            appl->NullCREnable = FALSE;
+            appl->NullCREnable = false;
           }
           plci_remove(plci);
         }
@@ -4862,7 +4862,7 @@
     byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
     byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
     byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
-  byte force_mt_info = FALSE;
+  byte force_mt_info = false;
   byte dir;
   dword d;
   word w;
@@ -4933,7 +4933,7 @@
   {
     if(plci->cr_enquiry && plci->appl)
     {
-      plci->cr_enquiry = FALSE;
+      plci->cr_enquiry = false;
       /* d = MANU_ID            */
       /* w = m_command          */
       /* b = total length       */
@@ -5158,7 +5158,7 @@
         if(application[i].CDEnable)
         {
           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
-          application[i].CDEnable = FALSE;
+          application[i].CDEnable = false;
         }
       }
       break;
@@ -5375,7 +5375,7 @@
         if(application[i].CDEnable)
         {
           if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
-          application[i].CDEnable = FALSE;
+          application[i].CDEnable = false;
         }
       }
       break;
@@ -5730,7 +5730,7 @@
                         plci,
                         Id,
                         parms,
-                        SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, TRUE));
+                        SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, true));
         }
       }
       clear_c_ind_mask_bit (plci, MAX_APPL);
@@ -6117,38 +6117,38 @@
         dbug(1,dprintf("CPN "));
         Info_Number = 0x0070;
         Info_Mask   = 0x80;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       case 8:  /* display      */
         dbug(1,dprintf("display(%d)",i));
         Info_Number = 0x0028;
         Info_Mask = 0x04;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       case 16: /* Channel Id */
         dbug(1,dprintf("CHI"));
         Info_Number = 0x0018;
         Info_Mask = 0x100;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         mixer_set_bchannel_id (plci, Info_Element);
         break;
       case 19: /* Redirected Number */
         dbug(1,dprintf("RDN"));
         Info_Number = 0x0074;
         Info_Mask = 0x400;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       case 20: /* Redirected Number extended */
         dbug(1,dprintf("RDX"));
         Info_Number = 0x0073;
         Info_Mask = 0x400;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       case 22: /* Redirecing Number  */
         dbug(1,dprintf("RIN"));
         Info_Number = 0x0076;
         Info_Mask = 0x400;
-        Info_Sent_Flag = TRUE;
+        Info_Sent_Flag = true;
         break;
       default:
         Info_Number = 0;
@@ -6312,7 +6312,7 @@
         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
         {
           dbug(1,dprintf("NCR_Ind"));
-          iesent=TRUE;
+          iesent=true;
           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
         }
       }
@@ -6330,7 +6330,7 @@
           if(test_c_ind_mask_bit (plci, j))
           {
             dbug(1,dprintf("Ovl_Ind"));
-            iesent=TRUE;
+            iesent=true;
             sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
           }
         }
@@ -6340,7 +6340,7 @@
     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
     {
       dbug(1,dprintf("Std_Ind"));
-      iesent=TRUE;
+      iesent=true;
       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
     }
   }
@@ -6391,7 +6391,7 @@
         && appl->Id
         && plci->adapter->Info_Mask[appl->Id-1] &Info_Mask)
         {
-          iesent = TRUE;
+          iesent = true;
           dbug(1,dprintf("Mlt_NCR_Ind"));
           sendf(&application[j],_INFO_I,Id&0x0f,0,"wS",Info_Number,Info_Element);
         }
@@ -6403,7 +6403,7 @@
       {
         if(test_c_ind_mask_bit (plci, j))
         {
-          iesent = TRUE;
+          iesent = true;
           dbug(1,dprintf("Mlt_Ovl_Ind"));
           sendf(&application[j],_INFO_I,Id,0,"wS",Info_Number,Info_Element);
         }
@@ -6412,7 +6412,7 @@
     else if(Info_Number
     && plci->adapter->Info_Mask[plci->appl->Id-1] &Info_Mask)
     {
-      iesent = TRUE;
+      iesent = true;
       dbug(1,dprintf("Mlt_Std_Ind"));
       sendf(plci->appl,_INFO_I,Id,0,"wS",Info_Number,Info_Element);
     }
@@ -6812,7 +6812,7 @@
         }
         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
         {
-          if (((T30_INFO   *)plci->NL.RBuffer->P)->code < sizeof(fax_info) / sizeof(fax_info[0]))
+	  if (((T30_INFO   *)plci->NL.RBuffer->P)->code < ARRAY_SIZE(fax_info))
             info = fax_info[((T30_INFO   *)plci->NL.RBuffer->P)->code];
           else
             info = _FAX_PROTOCOL_ERROR;
@@ -6887,7 +6887,7 @@
           (byte)(plci->ncpi_buffer[0] + 1), plci->ncpi_buffer);
         plci->ncpi_state |= NCPI_NEGOTIATE_B3_SENT;
  if (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)
-   fax_send_edata_ack = FALSE;
+   fax_send_edata_ack = false;
       }
 
       if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
@@ -6928,7 +6928,7 @@
             sendf(plci->appl,_DISCONNECT_B3_I,Id,0,"wS",GOOD,plci->ncpi_buffer);
             a->ncci_state[ncci] = INC_DIS_PENDING;
             plci->ncpi_state = 0;
-     fax_send_edata_ack = FALSE;
+     fax_send_edata_ack = false;
           }
           break;
         }
@@ -7025,7 +7025,7 @@
     }
     if (plci->adjust_b_restore)
     {
-      plci->adjust_b_restore = FALSE;
+      plci->adjust_b_restore = false;
       start_internal_command (Id, plci, adjust_b_restore);
     }
     break;
@@ -7041,7 +7041,7 @@
         next_internal_command (Id, plci);
     }
     ncci_state = a->ncci_state[ncci];
-    ncci_remove (plci, ncci, FALSE);
+    ncci_remove (plci, ncci, false);
 
         /* with N_DISC or N_DISC_ACK the IDI frees the respective   */
         /* channel, so we cannot store the state in ncci_state! The */
@@ -7288,18 +7288,18 @@
   plci->msg_in_read_pos = MSG_IN_QUEUE_SIZE;
   plci->msg_in_wrap_pos = MSG_IN_QUEUE_SIZE;
 
-  plci->data_sent = FALSE;
+  plci->data_sent = false;
   plci->send_disc = 0;
   plci->sig_global_req = 0;
   plci->sig_remove_id = 0;
   plci->nl_global_req = 0;
   plci->nl_remove_id = 0;
   plci->adv_nl = 0;
-  plci->manufacturer = FALSE;
+  plci->manufacturer = false;
   plci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
   plci->spoofed_msg = 0;
   plci->ptyState = 0;
-  plci->cr_enquiry = FALSE;
+  plci->cr_enquiry = false;
   plci->hangup_flow_ctrl_timer = 0;
 
   plci->ncci_ring_list = 0;
@@ -7972,7 +7972,7 @@
 
   if(!bp->length && plci->tel)
   {
-    plci->adv_nl = TRUE;
+    plci->adv_nl = true;
     dbug(1,dprintf("Default adv.Nl"));
     add_p(plci,LLI,lli);
     plci->B2_prot = 1 /*XPARENT*/;
@@ -8022,7 +8022,7 @@
   {  
     if(GET_WORD(bp_parms[1].info)!=1
     || GET_WORD(bp_parms[2].info)!=0) return _B2_NOT_SUPPORTED;
-    plci->adv_nl = TRUE;
+    plci->adv_nl = true;
   }
   else if(plci->tel) return _B2_NOT_SUPPORTED;
 
@@ -8840,7 +8840,7 @@
             plci->NL.X = plci->NData;
             plci->NL.ReqCh = a->ncci_ch[ncci];
             dbug(1,dprintf("%x:DREQ(%x:%x)",a->Id,plci->NL.Id,plci->NL.Req));
-            plci->data_sent = TRUE;
+            plci->data_sent = true;
             plci->data_sent_ptr = data->P;
             a->request(&plci->NL);
           }
@@ -8995,10 +8995,10 @@
 byte ie_compare(byte   * ie1, byte * ie2)
 {
   word i;
-  if(!ie1 || ! ie2) return FALSE;
-  if(!ie1[0]) return FALSE;
-  for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return FALSE;
-  return TRUE;
+  if(!ie1 || ! ie2) return false;
+  if(!ie1[0]) return false;
+  for(i=0;i<(word)(ie1[0]+1);i++) if(ie1[i]!=ie2[i]) return false;
+  return true;
 }
 
 word find_cip(DIVA_CAPI_ADAPTER   * a, byte   * bc, byte   * hlc)
@@ -9151,7 +9151,7 @@
         plci->tel=ADV_VOICE;
       }
       a->AdvSignalAppl = appl;
-      a->AdvCodecFLAG = TRUE;
+      a->AdvCodecFLAG = true;
       a->AdvCodecPLCI = splci;
       add_p(splci,CAI,"\x01\x15");
       add_p(splci,LLI,"\x01\x00");
@@ -9183,7 +9183,7 @@
         add_p(splci,UID,"\x06\x43\x61\x70\x69\x32\x30");
         sig_req(splci,ASSIGN,0xC0);  /* 0xc0 is the TEL_ID */
         send_req(splci);
-        a->scom_appl_disable = TRUE;
+        a->scom_appl_disable = true;
       }
       else{
         return 0x2001; /* wrong state, no more plcis */
@@ -9411,7 +9411,7 @@
       }
       if(a->AdvSignalAppl==this)
       {
-        this->NullCREnable = FALSE;
+        this->NullCREnable = false;
         if (a->AdvCodecPLCI)
         {
           plci_remove(a->AdvCodecPLCI);
@@ -9433,7 +9433,7 @@
 
 static word plci_remove_check(PLCI   *plci)
 {
-  if(!plci) return TRUE;
+  if(!plci) return true;
   if(!plci->NL.Id && c_ind_mask_empty (plci))
   {
     if(plci->Sig.Id == 0xff)
@@ -9446,7 +9446,7 @@
       {
         CodecIdCheck(plci->adapter, plci);
         clear_b1_config (plci);
-        ncci_remove (plci, 0, FALSE);
+        ncci_remove (plci, 0, false);
         plci_free_msg_in_queue (plci);
         channel_flow_control_remove (plci);
         plci->Id = 0;
@@ -9456,10 +9456,10 @@
         plci->notifiedcall = 0;
       }
       listen_check(plci->adapter);
-      return TRUE;
+      return true;
     }
   }
-  return FALSE;
+  return false;
 }
 
 
@@ -9564,7 +9564,7 @@
 
 };
 
-#define DTMF_DIGIT_MAP_ENTRIES (sizeof(dtmf_digit_map) / sizeof(dtmf_digit_map[0]))
+#define DTMF_DIGIT_MAP_ENTRIES ARRAY_SIZE(dtmf_digit_map)
 
 
 static void dtmf_enable_receiver (PLCI   *plci, byte enable_mask)
@@ -9815,7 +9815,7 @@
         }
         plci->dtmf_rec_active &= ~mask;
         plci->internal_command = DTMF_COMMAND_2;
-        dtmf_enable_receiver (plci, FALSE);
+        dtmf_enable_receiver (plci, false);
         return;
       }
       Rc = OK;
@@ -10020,7 +10020,7 @@
           }
         }
         start_internal_command (Id, plci, dtmf_command);
-        return (FALSE);
+        return (false);
 
 
       case DTMF_SEND_TONE:
@@ -10069,8 +10069,7 @@
           PUT_WORD (&result[1], DTMF_INCORRECT_DIGIT);
           break;
         }
-        if (plci->dtmf_send_requests >=
-          sizeof(plci->dtmf_msg_number_queue) / sizeof(plci->dtmf_msg_number_queue[0]))
+        if (plci->dtmf_send_requests >= ARRAY_SIZE(plci->dtmf_msg_number_queue))
         {
           dbug (1, dprintf ("[%06lx] %s,%d: DTMF request overrun",
             UnMapId (Id), (char   *)(FILE_), __LINE__));
@@ -10079,7 +10078,7 @@
         }
         api_save_msg (dtmf_parms, "wwws", &plci->saved_msg);
         start_internal_command (Id, plci, dtmf_command);
-        return (FALSE);
+        return (false);
 
       default:
         dbug (1, dprintf ("[%06lx] %s,%d: DTMF unknown request %04x",
@@ -10090,7 +10089,7 @@
   }
   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
     "wws", Info, SELECTOR_DTMF, result);
-  return (FALSE);
+  return (false);
 }
 
 
@@ -10842,10 +10841,10 @@
   byte to_pc;
 } xconnect_write_prog[] =
 {
-  { LI_COEF_CH_CH, FALSE, FALSE },
-  { LI_COEF_CH_PC, FALSE, TRUE },
-  { LI_COEF_PC_CH, TRUE, FALSE },
-  { LI_COEF_PC_PC, TRUE, TRUE }
+  { LI_COEF_CH_CH, false, false },
+  { LI_COEF_CH_PC, false, true },
+  { LI_COEF_PC_CH, true, false },
+  { LI_COEF_PC_PC, true, true }
 };
 
 
@@ -10916,7 +10915,7 @@
   {
     dbug (1, dprintf ("[%06x] %s,%d: Channel id wiped out",
       UnMapId (Id), (char   *)(FILE_), __LINE__));
-    return (TRUE);
+    return (true);
   }
   i = a->li_base + (plci->li_bchannel_id - 1);
   j = plci->li_write_channel;
@@ -10927,7 +10926,7 @@
     {
       dbug (1, dprintf ("[%06lx] %s,%d: LI write coefs failed %02x",
         UnMapId (Id), (char   *)(FILE_), __LINE__, Rc));
-      return (FALSE);
+      return (false);
     }
   }
   if (li_config_table[i].adapter->manufacturer_features & MANUFACTURER_FEATURE_XCONNECT)
@@ -10969,7 +10968,7 @@
     {
       plci->internal_command = plci->li_write_command;
       if (plci_nl_busy (plci))
-        return (TRUE);
+        return (true);
       to_ch = (a->li_pri) ? plci->li_bchannel_id - 1 : 0;
       *(p++) = UDATA_REQUEST_XCONNECT_TO;
       do
@@ -11018,9 +11017,9 @@
             li_config_table[i].coef_table[j] ^= xconnect_write_prog[n].mask << 4;
           }
           n++;
-        } while ((n < sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
+        } while ((n < ARRAY_SIZE(xconnect_write_prog))
           && ((p - plci->internal_req_buffer) + 16 < INTERNAL_REQ_BUFFER_SIZE));
-        if (n == sizeof(xconnect_write_prog) / sizeof(xconnect_write_prog[0]))
+        if (n == ARRAY_SIZE(xconnect_write_prog))
         {
           do
           {
@@ -11050,7 +11049,7 @@
     {
       plci->internal_command = plci->li_write_command;
       if (plci_nl_busy (plci))
-        return (TRUE);
+        return (true);
       if (a->li_pri)
       {
         *(p++) = UDATA_REQUEST_SET_MIXER_COEFS_PRI_SYNC;
@@ -11090,7 +11089,7 @@
             ch_map[j+1] = (byte)(j+1);
           }
         }
-        for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
+        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
         {
           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
@@ -11127,7 +11126,7 @@
     {
       plci->internal_command = plci->li_write_command;
       if (plci_nl_busy (plci))
-        return (TRUE);
+        return (true);
       if (j < a->li_base)
         j = a->li_base;
       if (a->li_pri)
@@ -11140,7 +11139,7 @@
           w |= MIXER_FEATURE_ENABLE_RX_DATA;
         *(p++) = (byte) w;
         *(p++) = (byte)(w >> 8);
-        for (n = 0; n < sizeof(mixer_write_prog_pri) / sizeof(mixer_write_prog_pri[0]); n++)
+        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_pri); n++)
         {
           *(p++) = (byte)((plci->li_bchannel_id - 1) | mixer_write_prog_pri[n].line_flags);
           for (j = a->li_base; j < a->li_base + MIXER_CHANNELS_PRI; j++)
@@ -11196,7 +11195,7 @@
             ch_map[j+1] = (byte)(j+1);
           }
         }
-        for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
+        for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
         {
           i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
           j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
@@ -11232,7 +11231,7 @@
     plci->NL.Req = plci->nl_req = (byte) N_UDATA;
     plci->adapter->request (&plci->NL);
   }
-  return (TRUE);
+  return (true);
 }
 
 
@@ -11251,7 +11250,7 @@
   if (a->profile.Global_Options & GL_LINE_INTERCONNECT_SUPPORTED)
   {
     if (others)
-      plci->li_notify_update = TRUE;
+      plci->li_notify_update = true;
     i = 0;
     do
     {
@@ -11277,7 +11276,7 @@
        && (notify_plci->State)
        && notify_plci->NL.Id && !notify_plci->nl_remove_id)
       {
-        notify_plci->li_notify_update = TRUE;
+        notify_plci->li_notify_update = true;
         ((CAPI_MSG *) msg)->header.length = 18;
         ((CAPI_MSG *) msg)->header.appl_id = notify_plci->appl->Id;
         ((CAPI_MSG *) msg)->header.command = _FACILITY_R;
@@ -11299,12 +11298,12 @@
               (char   *)(FILE_), __LINE__,
               (dword)((notify_plci->Id << 8) | UnMapController (notify_plci->adapter->Id)), w));
           }
-          notify_plci->li_notify_update = FALSE;
+          notify_plci->li_notify_update = false;
         }
       }
     } while (others && (notify_plci != NULL));
     if (others)
-      plci->li_notify_update = FALSE;
+      plci->li_notify_update = false;
   }
 }
 
@@ -11318,7 +11317,7 @@
     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
     (char   *)(FILE_), __LINE__));
 
-  plci->li_notify_update = FALSE;
+  plci->li_notify_update = false;
   plci->li_plci_b_write_pos = 0;
   plci->li_plci_b_read_pos = 0;
   plci->li_plci_b_req_pos = 0;
@@ -12159,7 +12158,7 @@
         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
         if (plci_b == NULL)
           break;
-        li_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
+        li_update_connect (Id, a, plci, plci_b_id, true, li_flags);
         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_LAST_FLAG;
         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
         plci->li_plci_b_write_pos = plci_b_write_pos;
@@ -12188,7 +12187,7 @@
         plci_b_write_pos = plci->li_plci_b_write_pos;
         participant_parms_pos = 0;
         result_pos = 7;
-        li2_update_connect (Id, a, plci, UnMapId (Id), TRUE, li_flags);
+        li2_update_connect (Id, a, plci, UnMapId (Id), true, li_flags);
         while (participant_parms_pos < li_req_parms[1].length)
         {
           result[result_pos] = 6;
@@ -12224,7 +12223,7 @@
           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
           if (plci_b != NULL)
           {
-            li2_update_connect (Id, a, plci, plci_b_id, TRUE, li_flags);
+            li2_update_connect (Id, a, plci, plci_b_id, true, li_flags);
             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id |
               ((li_flags & (LI2_FLAG_INTERCONNECT_A_B | LI2_FLAG_INTERCONNECT_B_A |
               LI2_FLAG_PCCONNECT_A_B | LI2_FLAG_PCCONNECT_B_A)) ? 0 : LI_PLCI_B_DISC_FLAG);
@@ -12249,13 +12248,13 @@
       }
       mixer_calculate_coefs (a);
       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
-      mixer_notify_update (plci, TRUE);
+      mixer_notify_update (plci, true);
       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
       plci->command = 0;
       plci->li_cmd = GET_WORD (li_parms[0].info);
       start_internal_command (Id, plci, mixer_command);
-      return (FALSE);
+      return (false);
 
     case LI_REQ_DISCONNECT:
       if (li_parms[1].length == 4)
@@ -12283,7 +12282,7 @@
         plci_b = li_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[8]);
         if (plci_b == NULL)
           break;
-        li_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
+        li_update_connect (Id, a, plci, plci_b_id, false, 0);
         plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG | LI_PLCI_B_LAST_FLAG;
         plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
         plci->li_plci_b_write_pos = plci_b_write_pos;
@@ -12345,7 +12344,7 @@
           plci_b = li2_check_plci_b (Id, plci, plci_b_id, plci_b_write_pos, &result[result_pos - 2]);
           if (plci_b != NULL)
           {
-            li2_update_connect (Id, a, plci, plci_b_id, FALSE, 0);
+            li2_update_connect (Id, a, plci, plci_b_id, false, 0);
             plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
             plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
           }
@@ -12368,13 +12367,13 @@
       }
       mixer_calculate_coefs (a);
       plci->li_channel_bits = li_config_table[a->li_base + (plci->li_bchannel_id - 1)].channel;
-      mixer_notify_update (plci, TRUE);
+      mixer_notify_update (plci, true);
       sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
         "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
       plci->command = 0;
       plci->li_cmd = GET_WORD (li_parms[0].info);
       start_internal_command (Id, plci, mixer_command);
-      return (FALSE);
+      return (false);
 
     case LI_REQ_SILENT_UPDATE:
       if (!plci || !plci->State
@@ -12384,7 +12383,7 @@
       {
         dbug (1, dprintf ("[%06lx] %s,%d: Wrong state",
           UnMapId (Id), (char   *)(FILE_), __LINE__));
-        return (FALSE);
+        return (false);
       }
       plci_b_write_pos = plci->li_plci_b_write_pos;
       if (((plci->li_plci_b_read_pos > plci_b_write_pos) ? plci->li_plci_b_read_pos :
@@ -12392,7 +12391,7 @@
       {
         dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
           UnMapId (Id), (char   *)(FILE_), __LINE__));
-        return (FALSE);
+        return (false);
       }
       i = (plci_b_write_pos == 0) ? LI_PLCI_B_QUEUE_ENTRIES-1 : plci_b_write_pos - 1;
       if ((plci_b_write_pos == plci->li_plci_b_read_pos)
@@ -12408,7 +12407,7 @@
       plci->command = 0;
       plci->li_cmd = GET_WORD (li_parms[0].info);
       start_internal_command (Id, plci, mixer_command);
-      return (FALSE);
+      return (false);
 
     default:
       dbug (1, dprintf ("[%06lx] %s,%d: LI unknown request %04x",
@@ -12418,7 +12417,7 @@
   }
   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
     "wwS", Info, SELECTOR_LINE_INTERCONNECT, result);
-  return (FALSE);
+  return (false);
 }
 
 
@@ -12523,7 +12522,7 @@
     if (!plci->internal_command)
       next_internal_command (Id, plci);
   }
-  mixer_notify_update (plci, TRUE);
+  mixer_notify_update (plci, true);
 }
 
 
@@ -12547,12 +12546,12 @@
     dbug (1, dprintf ("[%06lx] %s,%d: LI request overrun",
       (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
       (char   *)(FILE_), __LINE__));
-    return (FALSE);
+    return (false);
   }
   plci->li_plci_b_queue[plci_b_write_pos] = plci_b_id | LI_PLCI_B_DISC_FLAG;
   plci_b_write_pos = (plci_b_write_pos == LI_PLCI_B_QUEUE_ENTRIES-1) ? 0 : plci_b_write_pos + 1;
   plci->li_plci_b_write_pos = plci_b_write_pos;
-  return (TRUE);
+  return (true);
 }
 
 
@@ -12596,7 +12595,7 @@
         }
         mixer_clear_config (plci);
         mixer_calculate_coefs (a);
-        mixer_notify_update (plci, TRUE);
+        mixer_notify_update (plci, true);
       }
       li_config_table[i].plci = NULL;
       plci->li_bchannel_id = 0;
@@ -12883,29 +12882,29 @@
           case EC_ENABLE_OPERATION:
             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_DISABLE_OPERATION:
             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
               LEC_RESET_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_FREEZE_COEFFICIENTS:
             plci->ec_idi_options |= LEC_FREEZE_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_RESUME_COEFFICIENT_UPDATE:
             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_RESET_COEFFICIENTS:
             plci->ec_idi_options |= LEC_RESET_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           default:
             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
@@ -12978,14 +12977,14 @@
           case EC_ENABLE_OPERATION:
             plci->ec_idi_options &= ~LEC_FREEZE_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           case EC_DISABLE_OPERATION:
             plci->ec_idi_options = LEC_ENABLE_ECHO_CANCELLER |
               LEC_MANUAL_DISABLE | LEC_ENABLE_NONLINEAR_PROCESSING |
               LEC_RESET_COEFFICIENTS;
             start_internal_command (Id, plci, ec_command);
-            return (FALSE);
+            return (false);
 
           default:
             dbug (1, dprintf ("[%06lx] %s,%d: EC unknown request %04x",
@@ -12999,7 +12998,7 @@
   sendf (appl, _FACILITY_R | CONFIRM, Id & 0xffffL, Number,
     "wws", Info, (appl->appl_flags & APPL_FLAG_PRIV_EC_SPEC) ?
     PRIV_SELECTOR_ECHO_CANCELLER : SELECTOR_ECHO_CANCELLER, result);
-  return (FALSE);
+  return (false);
 }
 
 
@@ -13178,7 +13177,7 @@
         ch_map[j] = (byte)(j + (plci->li_bchannel_id - 1));
         ch_map[j+1] = (byte)(j + (2 - plci->li_bchannel_id));
       }
-      for (n = 0; n < sizeof(mixer_write_prog_bri) / sizeof(mixer_write_prog_bri[0]); n++)
+      for (n = 0; n < ARRAY_SIZE(mixer_write_prog_bri); n++)
       {
         i = a->li_base + ch_map[mixer_write_prog_bri[n].to_ch];
         j = a->li_base + ch_map[mixer_write_prog_bri[n].from_ch];
@@ -13563,7 +13562,7 @@
     (dword)((plci->Id << 8) | UnMapController (plci->adapter->Id)),
     (char   *)(FILE_), __LINE__));
 
-  plci->adjust_b_restore = FALSE;
+  plci->adjust_b_restore = false;
 }
 
 
@@ -13832,7 +13831,7 @@
     }
     if (plci->adjust_b_mode & ADJUST_B_MODE_USER_CONNECT)
     {
-      plci->adjust_b_restore = TRUE;
+      plci->adjust_b_restore = true;
       break;
     }
     plci->adjust_b_state = ADJUST_B_CONNECT_1;
@@ -14603,7 +14602,7 @@
 
 static void channel_xmit_extended_xon (PLCI   * plci) {
   DIVA_CAPI_ADAPTER   * a;
-  int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
+  int max_ch = ARRAY_SIZE(a->ch_flow_control);
   int i, one_requested = 0;
 
   if ((!plci) || (!plci->Id) || ((a = plci->adapter) == 0)) {
@@ -14628,7 +14627,7 @@
   Try to xmit next X_ON
   */
 static int find_channel_with_pending_x_on (DIVA_CAPI_ADAPTER   * a, PLCI   * plci) {
-  int max_ch = sizeof(a->ch_flow_control)/sizeof(a->ch_flow_control[0]);
+  int max_ch = ARRAY_SIZE(a->ch_flow_control);
   int i;
 
   if (!(plci->adapter->manufacturer_features & MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL)) {
@@ -14768,19 +14767,19 @@
   {
     if(application[i].Id && a->CIP_Mask[i] )
     {
-      for(k=0,busy=FALSE; k<a->max_plci; k++)
+      for(k=0,busy=false; k<a->max_plci; k++)
       {
         if(a->plci[k].Id) 
         {
           auxplci = &a->plci[k];
           if(auxplci->appl == &application[i]) /* application has a busy PLCI */
           {
-            busy = TRUE;
+            busy = true;
             dbug(1,dprintf("Appl 0x%x is busy",i+1));
           }
           else if(test_c_ind_mask_bit (auxplci, i)) /* application has an incoming call pending */
           {
-            busy = TRUE;
+            busy = true;
             dbug(1,dprintf("Appl 0x%x has inc. call pending",i+1));
           }
         }
@@ -14791,13 +14790,13 @@
         if(j==MAX_CIP_TYPES)       /* all groups are in use but group still not found */
         {                           /* the MAX_CIP_TYPES group enables all calls because of field overflow */
           appl_number_group_type[i] = MAX_CIP_TYPES;
-          group_found=TRUE;
+          group_found=true;
           dbug(1,dprintf("Field overflow appl 0x%x",i+1));
         }
         else if( (info_mask_group[j]==a->CIP_Mask[i]) && (cip_mask_group[j]==a->Info_Mask[i]) )  
         {                                      /* is group already present ?                  */
           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
-          group_found=TRUE;
+          group_found=true;
           dbug(1,dprintf("Group 0x%x found with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
         }
         else if(!info_mask_group[j])
@@ -14805,7 +14804,7 @@
           appl_number_group_type[i] = j|0x80;  /* store the group number for each application */
           info_mask_group[j] = a->CIP_Mask[i]; /* store the new CIP mask for the new group    */
           cip_mask_group[j] = a->Info_Mask[i]; /* store the new Info_Mask for this new group  */
-          group_found=TRUE;
+          group_found=true;
           dbug(1,dprintf("New Group 0x%x established with appl 0x%x, CIP=0x%lx",appl_number_group_type[i],i+1,info_mask_group[j]));
         }
       }
@@ -14860,7 +14859,7 @@
     }
   }
 
-  if(appls_found) return TRUE;
+  if(appls_found) return true;
   for(i=0; i<max_adapter; i++)                   /* scan all adapters...    */
   {
     a = &adapter[i];
@@ -14889,7 +14888,7 @@
       }
     }
   }
-  return FALSE;
+  return false;
 }
 
 /*------------------------------------------------------------------*/
diff --git a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c
index a296a84..9033565 100644
--- a/drivers/isdn/hardware/eicon/os_pri.c
+++ b/drivers/isdn/hardware/eicon/os_pri.c
@@ -487,7 +487,7 @@
 	}
 	DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot);
 
-	IoAdapter->Initialized = TRUE;
+	IoAdapter->Initialized = true;
 
 	/*
 	   Check Interrupt
@@ -504,7 +504,7 @@
 	if (!IoAdapter->IrqCount) {
 		DBG_ERR(("A: A(%d) interrupt test failed",
 			 IoAdapter->ANum))
-		IoAdapter->Initialized = FALSE;
+		IoAdapter->Initialized = false;
 		IoAdapter->stop(IoAdapter);
 		return (-1);
 	}
diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
index 2444811..ff09f07 100644
--- a/drivers/isdn/hardware/eicon/platform.h
+++ b/drivers/isdn/hardware/eicon/platform.h
@@ -71,14 +71,6 @@
 #define	qword  u64
 #endif
 
-#ifndef	TRUE
-#define	TRUE	1
-#endif
-
-#ifndef	FALSE
-#define	FALSE	0
-#endif
-
 #ifndef	NULL
 #define	NULL	((void *) 0)
 #endif
@@ -131,10 +123,6 @@
 #define DIVA_OS_MEM_DETACH_CONFIG(a, x)	do { } while(0)
 #define DIVA_OS_MEM_DETACH_CONTROL(a, x)	do { } while(0)
 
-#if !defined(DIM)
-#define DIM(array)  (sizeof (array)/sizeof ((array)[0]))
-#endif
-
 #define DIVA_INVALID_FILE_HANDLE  ((dword)(-1))
 
 #define DIVAS_CONTAINING_RECORD(address, type, field) \
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index 34ab5f7..12d91fb 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -340,8 +340,6 @@
 	  This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA
 	  cards. This code is not finished yet.
 
-#      bool '  TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
-
 config HISAX_ENTERNOW_PCI
 	bool "Formula-n enter:now PCI card"
 	depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index 293e277..c7a3794 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -60,5 +60,4 @@
 hisax-$(CONFIG_HISAX_GAZEL)		+= gazel.o isac.o arcofi.o hscx.o
 hisax-$(CONFIG_HISAX_W6692)		+= w6692.o
 hisax-$(CONFIG_HISAX_ENTERNOW_PCI)	+= enternow_pci.o amd7930_fn.o
-#hisax-$(CONFIG_HISAX_TESTEMU)		+= testemu.o
 
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 17ec0b7..da4196f 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -549,10 +549,6 @@
 extern int setup_saphir(struct IsdnCard *card);
 #endif
 
-#if CARD_TESTEMU
-extern int setup_testemu(struct IsdnCard *card);
-#endif
-
 #if CARD_BKM_A4T
 extern int setup_bkm_a4t(struct IsdnCard *card);
 #endif
@@ -1061,11 +1057,6 @@
 		ret = setup_saphir(card);
 		break;
 #endif
-#if CARD_TESTEMU
-	case ISDN_CTYPE_TESTEMU:
-		ret = setup_testemu(card);
-		break;
-#endif
 #if	CARD_BKM_A4T
 	case ISDN_CTYPE_BKM_A4T:
 		ret = setup_bkm_a4t(card);
@@ -1881,7 +1872,7 @@
 	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_DJINN_ITOO,   PCI_ANY_ID, PCI_ANY_ID},
 	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_OLITEC,       PCI_ANY_ID, PCI_ANY_ID},
 #endif
-#ifdef CONFIG_HISAX_QUADRO
+#ifdef CONFIG_HISAX_SCT_QUADRO
 	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_9050,         PCI_ANY_ID, PCI_ANY_ID},
 #endif
 #ifdef CONFIG_HISAX_NICCY
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
index 0279fb3..ae377e8 100644
--- a/drivers/isdn/hisax/elsa_ser.c
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -58,7 +58,7 @@
 static inline unsigned int serial_inp(struct IsdnCardState *cs, int offset)
 {
 #ifdef SERIAL_DEBUG_REG
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
+#ifdef ELSA_SERIAL_NOPAUSE_IO
 	u_int val = inb(cs->hw.elsa.base + 8 + offset);
 	debugl1(cs,"inp  %s %02x",ModemIn[offset], val);
 #else
@@ -67,7 +67,7 @@
 #endif
 	return(val);
 #else
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
+#ifdef ELSA_SERIAL_NOPAUSE_IO
 	return inb(cs->hw.elsa.base + 8 + offset);
 #else
 	return inb_p(cs->hw.elsa.base + 8 + offset);
@@ -87,13 +87,13 @@
 			       int value)
 {
 #ifdef SERIAL_DEBUG_REG
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
+#ifdef ELSA_SERIAL_NOPAUSE_IO
 	debugl1(cs,"outp %s %02x",ModemOut[offset], value);
 #else
 	debugl1(cs,"outP %s %02x",ModemOut[offset], value);
 #endif
 #endif
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
+#ifdef ELSA_SERIAL_NOPAUSE_IO
 	outb(value, cs->hw.elsa.base + 8 + offset);
 #else
     	outb_p(value, cs->hw.elsa.base + 8 + offset);
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index a2fa4ec..ab98e13 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -199,7 +199,7 @@
 /***************************/
 /* inline function defines */
 /***************************/
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM	/* inline functions mempry mapped */
+#ifdef HISAX_HFC4S8S_PCIMEM	/* inline functions memory mapped */
 
 /* memory write and dummy IO read to avoid PCI byte merge problems */
 #define Write_hfc8(a,b,c) {(*((volatile u_char *)(a->membase+b)) = c); inb(a->iobase+4);}
@@ -305,7 +305,7 @@
 
 #define PCI_ENA_REGIO	0x01
 
-#endif				/* CONFIG_HISAX_HFC4S8S_PCIMEM */
+#endif				/* HISAX_HFC4S8S_PCIMEM */
 
 /******************************************************/
 /* function to read critical counter registers that   */
@@ -724,12 +724,12 @@
 			} else {
 				/* read errornous D frame */
 
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 				SetRegAddr(l1p->hw, A_FIFO_DATA0);
 #endif
 
 				while (z1 >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 					Read_hfc32(l1p->hw, A_FIFO_DATA0);
 #else
 					fRead_hfc32(l1p->hw);
@@ -738,7 +738,7 @@
 				}
 
 				while (z1--)
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 					Read_hfc8(l1p->hw, A_FIFO_DATA0);
 #else
 					fRead_hfc8(l1p->hw);
@@ -752,12 +752,12 @@
 
 		cp = skb->data;
 
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(l1p->hw, A_FIFO_DATA0);
 #endif
 
 		while (z1 >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			*((unsigned long *) cp) =
 			    Read_hfc32(l1p->hw, A_FIFO_DATA0);
 #else
@@ -768,7 +768,7 @@
 		}
 
 		while (z1--)
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			*cp++ = Read_hfc8(l1p->hw, A_FIFO_DATA0);
 #else
 			*cp++ = fRead_hfc8(l1p->hw);
@@ -858,12 +858,12 @@
 			wait_busy(l1->hw);
 			return;
 		}
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(l1->hw, A_FIFO_DATA0);
 #endif
 
 		while (z1 >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			*((unsigned long *) bch->rx_ptr) =
 			    Read_hfc32(l1->hw, A_FIFO_DATA0);
 #else
@@ -875,7 +875,7 @@
 		}
 
 		while (z1--)
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			*(bch->rx_ptr++) = Read_hfc8(l1->hw, A_FIFO_DATA0);
 #else
 			*(bch->rx_ptr++) = fRead_hfc8(l1->hw);
@@ -939,12 +939,12 @@
 	if ((skb = skb_dequeue(&l1p->d_tx_queue))) {
 		cp = skb->data;
 		cnt = skb->len;
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(l1p->hw, A_FIFO_DATA0);
 #endif
 
 		while (cnt >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			fWrite_hfc32(l1p->hw, A_FIFO_DATA0,
 				     *(unsigned long *) cp);
 #else
@@ -955,7 +955,7 @@
 			cnt -= 4;
 		}
 
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 		while (cnt--)
 			fWrite_hfc8(l1p->hw, A_FIFO_DATA0, *cp++);
 #else
@@ -1036,11 +1036,11 @@
 		cp = skb->data + bch->tx_cnt;
 		bch->tx_cnt += cnt;
 
-#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(l1->hw, A_FIFO_DATA0);
 #endif
 		while (cnt >= 4) {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			fWrite_hfc32(l1->hw, A_FIFO_DATA0,
 				     *(unsigned long *) cp);
 #else
@@ -1051,7 +1051,7 @@
 		}
 
 		while (cnt--)
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 			fWrite_hfc8(l1->hw, A_FIFO_DATA0, *cp++);
 #else
 			fWrite_hfc8(l1->hw, *cp++);
@@ -1280,7 +1280,7 @@
 	if (!hw || !(hw->mr.r_irq_ctrl & M_GLOB_IRQ_EN))
 		return IRQ_NONE;
 
-#ifndef	CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef	HISAX_HFC4S8S_PCIMEM
 	/* read current selected regsister */
 	old_ioreg = GetRegAddr(hw);
 #endif
@@ -1291,7 +1291,7 @@
 	if (!
 	    (b = (Read_hfc8(hw, R_STATUS) & (M_MISC_IRQSTA | M_FR_IRQSTA)))
 && !hw->mr.r_irq_statech) {
-#ifndef	CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef	HISAX_HFC4S8S_PCIMEM
 		SetRegAddr(hw, old_ioreg);
 #endif
 		return IRQ_NONE;
@@ -1321,7 +1321,7 @@
 	/* queue the request to allow other cards to interrupt */
 	schedule_work(&hw->tqueue);
 
-#ifndef	CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifndef	HISAX_HFC4S8S_PCIMEM
 	SetRegAddr(hw, old_ioreg);
 #endif
 	return IRQ_HANDLED;
@@ -1470,7 +1470,7 @@
 release_pci_ports(hfc4s8s_hw * hw)
 {
 	pci_write_config_word(hw->pdev, PCI_COMMAND, 0);
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 	if (hw->membase)
 		iounmap((void *) hw->membase);
 #else
@@ -1485,7 +1485,7 @@
 static void
 enable_pci_ports(hfc4s8s_hw * hw)
 {
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 	pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_MEMIO);
 #else
 	pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_REGIO);
@@ -1560,7 +1560,7 @@
 		       hw->irq);
 		goto out;
 	}
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 	printk(KERN_INFO
 	       "HFC-4S/8S: found PCI card at membase 0x%p, irq %d\n",
 	       hw->hw_membase, hw->irq);
@@ -1613,7 +1613,7 @@
 	hw->irq = pdev->irq;
 	hw->iobase = pci_resource_start(pdev, 0);
 
-#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+#ifdef HISAX_HFC4S8S_PCIMEM
 	hw->hw_membase = (u_char *) pci_resource_start(pdev, 1);
 	hw->membase = ioremap((ulong) hw->hw_membase, 256);
 #else
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index 5a6989f..42bbae2 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -183,7 +183,7 @@
 	int vend_idx;		/* vendor found */
 	int b_mode[2];		/* B-channel mode */
 	int l1_activated;	/* layer 1 activated */
-	int disc_flag;		/* TRUE if device was disonnected to avoid some USB actions */
+	int disc_flag;		/* 'true' if device was disonnected to avoid some USB actions */
 	int packet_size, iso_packet_size;
 
 	/* control pipe background handling */
@@ -392,7 +392,7 @@
 	DBG(ISDN_DBG,
 	    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T3 expire)");
 #endif
-	hfc->l1_activated = FALSE;
+	hfc->l1_activated = false;
 	handle_led(hfc, LED_S0_OFF);
 	/* deactivate : */
 	queue_control_request(hfc, HFCUSB_STATES, 0x10, 1);
@@ -411,7 +411,7 @@
 	DBG(ISDN_DBG,
 	    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T4 expire)");
 #endif
-	hfc->l1_activated = FALSE;
+	hfc->l1_activated = false;
 	handle_led(hfc, LED_S0_OFF);
 }
 
@@ -452,7 +452,7 @@
 #ifdef CONFIG_HISAX_DEBUG
 		DBG(ISDN_DBG, "HFC-S USB: PH_ACTIVATE | INDICATION sent");
 #endif
-		hfc->l1_activated = TRUE;
+		hfc->l1_activated = true;
 		handle_led(hfc, LED_S0_ON);
 	} else if (state <= 3 /* && activated */ ) {
 		if (old_state == 7 || old_state == 8) {
@@ -472,7 +472,7 @@
 			DBG(ISDN_DBG,
 			    "HFC-S USB: PH_DEACTIVATE | INDICATION sent");
 #endif
-			hfc->l1_activated = FALSE;
+			hfc->l1_activated = false;
 			handle_led(hfc, LED_S0_OFF);
 		}
 	}
@@ -622,7 +622,7 @@
 	if (fifo->active && !status) {
 		transp_mode = 0;
 		if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
-			transp_mode = TRUE;
+			transp_mode = true;
 
 		/* is FifoFull-threshold set for our channel? */
 		threshbit = threshtable[fifon] & hfc->threshold_mask;
@@ -640,7 +640,7 @@
 			      tx_iso_complete, urb->context);
 		memset(context_iso_urb->buffer, 0,
 		       sizeof(context_iso_urb->buffer));
-		frame_complete = FALSE;
+		frame_complete = false;
 		/* Generate next Iso Packets */
 		for (k = 0; k < num_isoc_packets; ++k) {
 			if (fifo->skbuff) {
@@ -666,7 +666,7 @@
 						/* add 2 byte flags and 16bit CRC at end of ISDN frame */
 						fifo->bit_line += 32;
 					}
-					frame_complete = TRUE;
+					frame_complete = true;
 				}
 
 				memcpy(context_iso_urb->buffer +
@@ -693,7 +693,7 @@
 			}
 
 			if (frame_complete) {
-				fifo->delete_flg = TRUE;
+				fifo->delete_flg = true;
 				fifo->hif->l1l2(fifo->hif,
 						PH_DATA | CONFIRM,
 						(void *) (unsigned long) fifo->skbuff->
@@ -701,9 +701,9 @@
 				if (fifo->skbuff && fifo->delete_flg) {
 					dev_kfree_skb_any(fifo->skbuff);
 					fifo->skbuff = NULL;
-					fifo->delete_flg = FALSE;
+					fifo->delete_flg = false;
 				}
-				frame_complete = FALSE;
+				frame_complete = false;
 			}
 		}
 		errcode = usb_submit_urb(urb, GFP_ATOMIC);
@@ -837,7 +837,7 @@
 	fifon = fifo->fifonum;
 	transp_mode = 0;
 	if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
-		transp_mode = TRUE;
+		transp_mode = true;
 
 	if (!fifo->skbuff) {
 		fifo->skbuff = dev_alloc_skb(fifo->max_size + 3);
@@ -1176,7 +1176,7 @@
 			if (fifo->skbuff && fifo->delete_flg) {
 				dev_kfree_skb_any(fifo->skbuff);
 				fifo->skbuff = NULL;
-				fifo->delete_flg = FALSE;
+				fifo->delete_flg = false;
 			}
 			fifo->skbuff = arg;	/* we have a new buffer */
 			break;
@@ -1262,8 +1262,8 @@
 	hfc->b_mode[0] = L1_MODE_NULL;
 	hfc->b_mode[1] = L1_MODE_NULL;
 
-	hfc->l1_activated = FALSE;
-	hfc->disc_flag = FALSE;
+	hfc->l1_activated = false;
+	hfc->disc_flag = false;
 	hfc->led_state = 0;
 	hfc->led_new_data = 0;
 	hfc->old_led_state = 0;
@@ -1404,7 +1404,7 @@
 
 			/* check for config EOL element */
 			while (validconf[cfg_used][0]) {
-				cfg_found = TRUE;
+				cfg_found = true;
 				vcf = validconf[cfg_used];
 				/* first endpoint descriptor */
 				ep = iface->endpoint;
@@ -1426,7 +1426,7 @@
 						idx++;
 					attr = ep->desc.bmAttributes;
 					if (cmptbl[idx] == EP_NUL) {
-						cfg_found = FALSE;
+						cfg_found = false;
 					}
 					if (attr == USB_ENDPOINT_XFER_INT
 					    && cmptbl[idx] == EP_INT)
@@ -1448,7 +1448,7 @@
 							    "HFC-S USB: Interrupt Endpoint interval < %d found - skipping config",
 							    vcf[17]);
 #endif
-						cfg_found = FALSE;
+						cfg_found = false;
 					}
 					ep++;
 				}
@@ -1456,7 +1456,7 @@
 					/* all entries must be EP_NOP or EP_NUL for a valid config */
 					if (cmptbl[i] != EP_NOP
 					    && cmptbl[i] != EP_NUL)
-						cfg_found = FALSE;
+						cfg_found = false;
 				}
 				if (cfg_found) {
 					if (cfg_used < small_match) {
@@ -1656,7 +1656,7 @@
 	hfcusb_data *context = usb_get_intfdata(intf);
 	int i;
 	printk(KERN_INFO "HFC-S USB: device disconnect\n");
-	context->disc_flag = TRUE;
+	context->disc_flag = true;
 	usb_set_intfdata(intf, NULL);
 	if (!context)
 		return;
diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h
index 6349367..471f235 100644
--- a/drivers/isdn/hisax/hfc_usb.h
+++ b/drivers/isdn/hisax/hfc_usb.h
@@ -12,9 +12,6 @@
 
 #define VERBOSE_USB_DEBUG
 
-#define TRUE  1
-#define FALSE 0
-
 
 /***********/
 /* defines */
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 3f1137e..3cd8d5b 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -795,19 +795,6 @@
 	struct timer_list timer;
 };
 
-#ifdef  CONFIG_HISAX_TESTEMU
-struct te_hw {
-	unsigned char *sfifo;
-	unsigned char *sfifo_w;
-	unsigned char *sfifo_r;
-	unsigned char *sfifo_e;
-	int sfifo_cnt;
-	unsigned int stat;
-	wait_queue_head_t rwaitq;
-	wait_queue_head_t swaitq;
-};
-#endif
-
 struct arcofi_msg {
 	struct arcofi_msg *next;
 	u_char receive;
@@ -916,9 +903,6 @@
 		struct ix1_hw niccy;
 		struct isurf_hw isurf;
 		struct saphir_hw saphir;
-#ifdef CONFIG_HISAX_TESTEMU
-		struct te_hw te;
-#endif
 		struct bkm_hw ax;
 		struct gazel_hw gazel;
 		struct w6692_hw w6692;
@@ -1175,15 +1159,6 @@
 #define CARD_HSTSAPHIR 0
 #endif
 
-#ifdef	CONFIG_HISAX_TESTEMU
-#define	CARD_TESTEMU 1
-#define ISDN_CTYPE_TESTEMU 99
-#undef ISDN_CTYPE_COUNT
-#define  ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
-#else
-#define CARD_TESTEMU 0
-#endif
-
 #ifdef	CONFIG_HISAX_BKM_A4T
 #define	CARD_BKM_A4T 1
 #ifndef ISDN_CHIP_ISAC
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index 6f1a658..9df9e35 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -431,7 +431,6 @@
 	return(ret);
 }
 
-extern void BChannel_bh(struct BCState *);
 #define B_LL_NOCARRIER	8
 #define B_LL_CONNECT	9
 #define B_LL_OK		10
diff --git a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h
index 0e88cfa..172ad4c 100644
--- a/drivers/isdn/hisax/isdnl1.h
+++ b/drivers/isdn/hisax/isdnl1.h
@@ -21,12 +21,11 @@
 #define B_XMTBUFREADY	1
 #define B_ACKPENDING	2
 
-extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
-extern void DChannel_proc_xmt(struct IsdnCardState *cs);
-extern void DChannel_proc_rcv(struct IsdnCardState *cs);
-extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
-extern void l1_msg_b(struct PStack *st, int pr, void *arg);
-
-#ifdef L2FRAME_DEBUG
-extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
-#endif
+void debugl1(struct IsdnCardState *cs, char *fmt, ...);
+void DChannel_proc_xmt(struct IsdnCardState *cs);
+void DChannel_proc_rcv(struct IsdnCardState *cs);
+void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
+void l1_msg_b(struct PStack *st, int pr, void *arg);
+void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf,
+		int dir);
+void BChannel_bh(struct work_struct *work);
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index 281fa27..935f233 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -231,18 +231,6 @@
 	return(-1);
 }
 
-#ifdef	CONFIG_HISAX_EURO
-extern void setstack_dss1(struct PStack *st);
-#endif
-
-#ifdef  CONFIG_HISAX_NI1
-extern void setstack_ni1(struct PStack *st);
-#endif
-
-#ifdef	CONFIG_HISAX_1TR6
-extern void setstack_1tr6(struct PStack *st);
-#endif
-
 struct l3_process
 *getl3proc(struct PStack *st, int cr)
 {
diff --git a/drivers/isdn/hisax/isdnl3.h b/drivers/isdn/hisax/isdnl3.h
index 1dbe029..749498f 100644
--- a/drivers/isdn/hisax/isdnl3.h
+++ b/drivers/isdn/hisax/isdnl3.h
@@ -25,13 +25,19 @@
 
 #define l3_debug(st, fmt, args...) HiSax_putstatus(st->l1.hardware, "l3 ", fmt, ## args)
 
-extern void newl3state(struct l3_process *pc, int state);
-extern void L3InitTimer(struct l3_process *pc, struct L3Timer *t);
-extern void L3DelTimer(struct L3Timer *t);
-extern int L3AddTimer(struct L3Timer *t, int millisec, int event);
-extern void StopAllL3Timer(struct l3_process *pc);
-extern struct sk_buff *l3_alloc_skb(int len);
-extern struct l3_process *new_l3_process(struct PStack *st, int cr);
-extern void release_l3_process(struct l3_process *p);
-extern struct l3_process *getl3proc(struct PStack *st, int cr);
-extern void l3_msg(struct PStack *st, int pr, void *arg);
+struct PStack;
+
+void newl3state(struct l3_process *pc, int state);
+void L3InitTimer(struct l3_process *pc, struct L3Timer *t);
+void L3DelTimer(struct L3Timer *t);
+int L3AddTimer(struct L3Timer *t, int millisec, int event);
+void StopAllL3Timer(struct l3_process *pc);
+struct sk_buff *l3_alloc_skb(int len);
+struct l3_process *new_l3_process(struct PStack *st, int cr);
+void release_l3_process(struct l3_process *p);
+struct l3_process *getl3proc(struct PStack *st, int cr);
+void l3_msg(struct PStack *st, int pr, void *arg);
+void setstack_dss1(struct PStack *st);
+void setstack_ni1(struct PStack *st);
+void setstack_1tr6(struct PStack *st);
+
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 94a9350..dc477e0 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -367,7 +367,7 @@
 /******************************************************/
 /* table for conf filesystem functions defined above. */
 /******************************************************/
-static struct file_operations conf_fops =
+static const struct file_operations conf_fops =
 {
 	.llseek         = no_llseek,
 	.read           = hysdn_conf_read,
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
index 375d956..f7e83a8 100644
--- a/drivers/isdn/hysdn/hysdn_proclog.c
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -383,7 +383,7 @@
 /**************************************************/
 /* table for log filesystem functions defined above. */
 /**************************************************/
-static struct file_operations log_fops =
+static const struct file_operations log_fops =
 {
 	.llseek         = no_llseek,
 	.read           = hysdn_log_read,
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 6a2ef0a..9c926e4 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1822,7 +1822,7 @@
 	return 0;
 }
 
-static struct file_operations isdn_fops =
+static const struct file_operations isdn_fops =
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 11c1b0b..386c5ce 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -774,10 +774,6 @@
 	dev->dev_if->statcallb(&ictl);
 }
 	
-extern char * isdn_state_table[];
-extern char * strisdnevent(unsigned short);
-
-
 void pcbit_state_change(struct pcbit_dev * dev, struct pcbit_chan * chan, 
 			unsigned short i, unsigned short ev, unsigned short f)
 {
diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c
index 93ca7de..1ad8b07 100644
--- a/drivers/isdn/pcbit/edss1.c
+++ b/drivers/isdn/pcbit/edss1.c
@@ -35,12 +35,6 @@
 #include "callbacks.h"
 
 
-extern void pcbit_state_change(struct pcbit_dev *, struct pcbit_chan *, 
-                               unsigned short i, unsigned short ev, 
-                               unsigned short f);
-
-extern struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS];
-
 char * isdn_state_table[] = {
   "Closed",
   "Call initiated",
diff --git a/drivers/isdn/pcbit/edss1.h b/drivers/isdn/pcbit/edss1.h
index 6bb5870..0b64f97 100644
--- a/drivers/isdn/pcbit/edss1.h
+++ b/drivers/isdn/pcbit/edss1.h
@@ -90,9 +90,12 @@
 	unsigned long timeout;          /* in seconds */
 };
 
+extern char * isdn_state_table[];
 
-extern void pcbit_fsm_event(struct pcbit_dev *, struct pcbit_chan *,
-			    unsigned short event, struct callb_data *);
+void pcbit_fsm_event(struct pcbit_dev *, struct pcbit_chan *,
+		     unsigned short event, struct callb_data *);
+char * strisdnevent(ushort ev);
+
 #endif
 
 
diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c
index eafcce5..58eee50 100644
--- a/drivers/isdn/pcbit/layer2.c
+++ b/drivers/isdn/pcbit/layer2.c
@@ -47,22 +47,6 @@
 #undef DEBUG_FRAG
 
 
-
-/*
- *  task queue struct
- */
-
-
-
-/*
- *  Layer 3 packet demultiplexer
- *  drv.c
- */
-
-extern void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg,
-			     struct sk_buff *skb,
-			     ushort hdr_len, ushort refnum);
-
 /*
  *  Prototypes
  */
diff --git a/drivers/isdn/pcbit/module.c b/drivers/isdn/pcbit/module.c
index 282073a..7b7b177 100644
--- a/drivers/isdn/pcbit/module.c
+++ b/drivers/isdn/pcbit/module.c
@@ -32,9 +32,6 @@
 static int num_boards;
 struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS];
 
-extern void pcbit_terminate(int board);
-extern int pcbit_init_dev(int board, int mem_base, int irq);
-
 static int __init pcbit_init(void)
 {
 	int board;
diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h
index 19c18e8..d76fffc 100644
--- a/drivers/isdn/pcbit/pcbit.h
+++ b/drivers/isdn/pcbit/pcbit.h
@@ -166,6 +166,12 @@
 #define L2_RUNNING  5
 #define L2_ERROR    6
 
-extern void pcbit_deliver(struct work_struct *work);
+void pcbit_deliver(struct work_struct *work);
+int pcbit_init_dev(int board, int mem_base, int irq);
+void pcbit_terminate(int board);
+void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, struct sk_buff * skb,
+		      ushort hdr_len, ushort refnum);
+void pcbit_state_change(struct pcbit_dev * dev, struct pcbit_chan * chan,
+			unsigned short i, unsigned short ev, unsigned short f);
 
 #endif
diff --git a/drivers/isdn/sc/card.h b/drivers/isdn/sc/card.h
index 8e44928..4fbfa82 100644
--- a/drivers/isdn/sc/card.h
+++ b/drivers/isdn/sc/card.h
@@ -26,7 +26,9 @@
 #include <linux/timer.h>
 #include <linux/time.h>
 #include <linux/isdnif.h>
+#include <linux/irqreturn.h>
 #include "message.h"
+#include "scioc.h"
 
 /*
  * Amount of time to wait for a reset to complete
@@ -98,4 +100,32 @@
 	spinlock_t lock;		/* local lock */
 } board;
 
+
+extern board *sc_adapter[];
+extern int cinst;
+
+void memcpy_toshmem(int card, void *dest, const void *src, size_t n);
+void memcpy_fromshmem(int card, void *dest, const void *src, size_t n);
+int get_card_from_id(int driver);
+int indicate_status(int card, int event, ulong Channel, char *Data);
+irqreturn_t interrupt_handler(int interrupt, void *cardptr);
+int sndpkt(int devId, int channel, struct sk_buff *data);
+void rcvpkt(int card, RspMessage *rcvmsg);
+int command(isdn_ctrl *cmd);
+int reset(int card);
+int startproc(int card);
+int send_and_receive(int card, unsigned int procid, unsigned char type,
+		     unsigned char class, unsigned char code,
+		     unsigned char link, unsigned char data_len,
+		     unsigned char *data,  RspMessage *mesgdata, int timeout);
+void flushreadfifo (int card);
+int sendmessage(int card, unsigned int procid, unsigned int type,
+		unsigned int class, unsigned int code, unsigned int link,
+		unsigned int data_len, unsigned int *data);
+int receivemessage(int card, RspMessage *rspmsg);
+int sc_ioctl(int card, scs_ioctl *data);
+int setup_buffers(int card, int c);
+void check_reset(unsigned long data);
+void check_phystat(unsigned long data);
+
 #endif /* CARD_H */
diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c
index 04b8a58..b7bb7cb 100644
--- a/drivers/isdn/sc/command.c
+++ b/drivers/isdn/sc/command.c
@@ -31,19 +31,6 @@
 static int setl3(int card, unsigned long arg);
 static int acceptb(int card, unsigned long channel);
 
-extern int cinst;
-extern board *sc_adapter[];
-
-extern int sc_ioctl(int, scs_ioctl *);
-extern int setup_buffers(int, int, unsigned int);
-extern int indicate_status(int, int,ulong,char*);
-extern void check_reset(unsigned long);
-extern int send_and_receive(int, unsigned int, unsigned char, unsigned char,
-                unsigned char, unsigned char, unsigned char, unsigned char *,
-                RspMessage *, int);
-extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
-                unsigned int, unsigned int, unsigned int, unsigned int *);
-
 #ifdef DEBUG
 /*
  * Translate command codes to strings
@@ -208,7 +195,7 @@
 		return -ENODEV;
 	}
 
-	if(setup_buffers(card, channel+1, BUFFER_SIZE)) {
+	if(setup_buffers(card, channel+1)) {
 		hangup(card, channel+1);
 		return -ENOBUFS;
 	}
@@ -297,7 +284,7 @@
 		return -ENODEV;
 	}
 
-	if(setup_buffers(card, channel+1, BUFFER_SIZE))
+	if(setup_buffers(card, channel+1))
 	{
 		hangup(card, channel+1);
 		return -ENOBUFS;
diff --git a/drivers/isdn/sc/event.c b/drivers/isdn/sc/event.c
index 5736732..498f403 100644
--- a/drivers/isdn/sc/event.c
+++ b/drivers/isdn/sc/event.c
@@ -20,9 +20,6 @@
 #include "message.h"
 #include "card.h"
 
-extern int cinst;
-extern board *sc_adapter[];
-
 #ifdef DEBUG
 static char *events[] = { "ISDN_STAT_STAVAIL",
 			  "ISDN_STAT_ICALL",
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 150759a..0bf7634 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -35,12 +35,6 @@
 module_param_array(ram, int, NULL, 0);
 module_param(do_reset, bool, 0);
 
-extern irqreturn_t interrupt_handler(int, void *);
-extern int sndpkt(int, int, int, struct sk_buff *);
-extern int command(isdn_ctrl *);
-extern int indicate_status(int, int, ulong, char*);
-extern int reset(int);
-
 static int identify_board(unsigned long, unsigned int);
 
 static int __init sc_init(void)
diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c
index cd17de1..bef7963 100644
--- a/drivers/isdn/sc/interrupt.c
+++ b/drivers/isdn/sc/interrupt.c
@@ -21,16 +21,6 @@
 #include "card.h"
 #include <linux/interrupt.h>
 
-extern int indicate_status(int, int, ulong, char *);
-extern void check_phystat(unsigned long);
-extern int receivemessage(int, RspMessage *);
-extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
-        unsigned int, unsigned int, unsigned int, unsigned int *);
-extern void rcvpkt(int, RspMessage *);
-
-extern int cinst;
-extern board *sc_adapter[];
-
 static int get_card_from_irq(int irq)
 {
 	int i;
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
index 57c4ab9..7817d22 100644
--- a/drivers/isdn/sc/ioctl.c
+++ b/drivers/isdn/sc/ioctl.c
@@ -12,16 +12,6 @@
 #include "card.h"
 #include "scioc.h"
 
-extern int indicate_status(int, int, unsigned long, char *);
-extern int startproc(int);
-extern int reset(int);
-extern int send_and_receive(int, unsigned int, unsigned char,unsigned char,
-		unsigned char,unsigned char, 
-		unsigned char, unsigned char *, RspMessage *, int);
-
-extern board *sc_adapter[];
-
-
 static int GetStatus(int card, boardInfo *);
 
 /*
diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c
index 0a0fe6b..c5a307e 100644
--- a/drivers/isdn/sc/message.c
+++ b/drivers/isdn/sc/message.c
@@ -22,16 +22,6 @@
 #include "message.h"
 #include "card.h"
 
-extern board *sc_adapter[];
-extern unsigned int cinst;
-
-/*
- * Obligatory function prototypes
- */
-extern int indicate_status(int,ulong,char*);
-extern int scm_command(isdn_ctrl *);
-
-
 /*
  * receive a message from the board
  */
diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
index 1e04676..92016a2 100644
--- a/drivers/isdn/sc/packet.c
+++ b/drivers/isdn/sc/packet.c
@@ -20,16 +20,6 @@
 #include "message.h"
 #include "card.h"
 
-extern board *sc_adapter[];
-extern unsigned int cinst;
-
-extern int get_card_from_id(int);
-extern int indicate_status(int, int,ulong, char*);
-extern void memcpy_toshmem(int, void *, const void *, size_t);
-extern void memcpy_fromshmem(int, void *, const void *, size_t);
-extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
-                unsigned int, unsigned int, unsigned int, unsigned int *);
-
 int sndpkt(int devId, int channel, struct sk_buff *data)
 {
 	LLData	ReqLnkWrite;
diff --git a/drivers/isdn/sc/scioc.h b/drivers/isdn/sc/scioc.h
index d08e650..dfb107a 100644
--- a/drivers/isdn/sc/scioc.h
+++ b/drivers/isdn/sc/scioc.h
@@ -1,3 +1,6 @@
+#ifndef __ISDN_SC_SCIOC_H__
+#define __ISDN_SC_SCIOC_H__
+
 /*
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
@@ -103,3 +106,6 @@
 		POTInfo potsinfo;
 	} info;
 } boardInfo;
+
+#endif  /*  __ISDN_SC_SCIOC_H__  */
+
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
index 6f58862..034d41a 100644
--- a/drivers/isdn/sc/shmem.c
+++ b/drivers/isdn/sc/shmem.c
@@ -22,12 +22,6 @@
 #include "card.h"
 
 /*
- * Main adapter array
- */
-extern board *sc_adapter[];
-extern int cinst;
-
-/*
  *
  */
 void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
diff --git a/drivers/isdn/sc/timer.c b/drivers/isdn/sc/timer.c
index f43282b..cc1b886 100644
--- a/drivers/isdn/sc/timer.c
+++ b/drivers/isdn/sc/timer.c
@@ -20,14 +20,6 @@
 #include "message.h"
 #include "card.h"
 
-extern board *sc_adapter[];
-
-extern void flushreadfifo(int);
-extern int  startproc(int);
-extern int  indicate_status(int, int, unsigned long, char *);
-extern int  sendmessage(int, unsigned int, unsigned int, unsigned int,
-        unsigned int, unsigned int, unsigned int, unsigned int *);
-
 
 /*
  * Write the proper values into the I/O ports following a reset
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 2db1ca4..04574a9 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -304,6 +304,7 @@
 	int memory_config_version;
 	int busy;
 	unsigned long rmap_overflow;
+	struct list_head vm_list;
 };
 
 struct kvm_stat {
@@ -340,6 +341,7 @@
 
 	struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu);
 	void (*vcpu_put)(struct kvm_vcpu *vcpu);
+	void (*vcpu_decache)(struct kvm_vcpu *vcpu);
 
 	int (*set_guest_debug)(struct kvm_vcpu *vcpu,
 			       struct kvm_debug_guest *dbg);
@@ -558,7 +560,7 @@
 #ifndef load_ldt
 static inline void load_ldt(u16 sel)
 {
-	asm ("lldt %0" : : "g"(sel));
+	asm ("lldt %0" : : "rm"(sel));
 }
 #endif
 
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 099f0af..af86614 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -34,6 +34,8 @@
 #include <linux/highmem.h>
 #include <linux/file.h>
 #include <asm/desc.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
 
 #include "x86_emulate.h"
 #include "segment_descriptor.h"
@@ -41,6 +43,9 @@
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+static DEFINE_SPINLOCK(kvm_lock);
+static LIST_HEAD(vm_list);
+
 struct kvm_arch_ops *kvm_arch_ops;
 struct kvm_stat kvm_stat;
 EXPORT_SYMBOL_GPL(kvm_stat);
@@ -230,9 +235,13 @@
 		struct kvm_vcpu *vcpu = &kvm->vcpus[i];
 
 		mutex_init(&vcpu->mutex);
+		vcpu->cpu = -1;
 		vcpu->kvm = kvm;
 		vcpu->mmu.root_hpa = INVALID_PAGE;
 		INIT_LIST_HEAD(&vcpu->free_pages);
+		spin_lock(&kvm_lock);
+		list_add(&kvm->vm_list, &vm_list);
+		spin_unlock(&kvm_lock);
 	}
 	filp->private_data = kvm;
 	return 0;
@@ -272,7 +281,9 @@
 
 static void kvm_free_vcpu(struct kvm_vcpu *vcpu)
 {
-	vcpu_load(vcpu->kvm, vcpu_slot(vcpu));
+	if (!vcpu_load(vcpu->kvm, vcpu_slot(vcpu)))
+		return;
+
 	kvm_mmu_destroy(vcpu);
 	vcpu_put(vcpu);
 	kvm_arch_ops->vcpu_free(vcpu);
@@ -290,6 +301,9 @@
 {
 	struct kvm *kvm = filp->private_data;
 
+	spin_lock(&kvm_lock);
+	list_del(&kvm->vm_list);
+	spin_unlock(&kvm_lock);
 	kvm_free_vcpus(kvm);
 	kvm_free_physmem(kvm);
 	kfree(kvm);
@@ -544,7 +558,6 @@
 					   FX_IMAGE_ALIGN);
 	vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE;
 
-	vcpu->cpu = -1;  /* First load will set up TR */
 	r = kvm_arch_ops->vcpu_create(vcpu);
 	if (r < 0)
 		goto out_free_vcpus;
@@ -1360,6 +1373,9 @@
 	if (!vcpu)
 		return -ENOENT;
 
+	/* re-sync apic's tpr */
+	vcpu->cr8 = kvm_run->cr8;
+
 	if (kvm_run->emulated) {
 		kvm_arch_ops->skip_emulated_instruction(vcpu);
 		kvm_run->emulated = 0;
@@ -2025,6 +2041,64 @@
 	.priority = 0,
 };
 
+/*
+ * Make sure that a cpu that is being hot-unplugged does not have any vcpus
+ * cached on it.
+ */
+static void decache_vcpus_on_cpu(int cpu)
+{
+	struct kvm *vm;
+	struct kvm_vcpu *vcpu;
+	int i;
+
+	spin_lock(&kvm_lock);
+	list_for_each_entry(vm, &vm_list, vm_list)
+		for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+			vcpu = &vm->vcpus[i];
+			/*
+			 * If the vcpu is locked, then it is running on some
+			 * other cpu and therefore it is not cached on the
+			 * cpu in question.
+			 *
+			 * If it's not locked, check the last cpu it executed
+			 * on.
+			 */
+			if (mutex_trylock(&vcpu->mutex)) {
+				if (vcpu->cpu == cpu) {
+					kvm_arch_ops->vcpu_decache(vcpu);
+					vcpu->cpu = -1;
+				}
+				mutex_unlock(&vcpu->mutex);
+			}
+		}
+	spin_unlock(&kvm_lock);
+}
+
+static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
+			   void *v)
+{
+	int cpu = (long)v;
+
+	switch (val) {
+	case CPU_DEAD:
+	case CPU_UP_CANCELED:
+		decache_vcpus_on_cpu(cpu);
+		smp_call_function_single(cpu, kvm_arch_ops->hardware_disable,
+					 NULL, 0, 1);
+		break;
+	case CPU_UP_PREPARE:
+		smp_call_function_single(cpu, kvm_arch_ops->hardware_enable,
+					 NULL, 0, 1);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block kvm_cpu_notifier = {
+	.notifier_call = kvm_cpu_hotplug,
+	.priority = 20, /* must be > scheduler priority */
+};
+
 static __init void kvm_init_debug(void)
 {
 	struct kvm_stats_debugfs_item *p;
@@ -2044,6 +2118,30 @@
 	debugfs_remove(debugfs_dir);
 }
 
+static int kvm_suspend(struct sys_device *dev, pm_message_t state)
+{
+	decache_vcpus_on_cpu(raw_smp_processor_id());
+	on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1);
+	return 0;
+}
+
+static int kvm_resume(struct sys_device *dev)
+{
+	on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1);
+	return 0;
+}
+
+static struct sysdev_class kvm_sysdev_class = {
+	set_kset_name("kvm"),
+	.suspend = kvm_suspend,
+	.resume = kvm_resume,
+};
+
+static struct sys_device kvm_sysdev = {
+	.id = 0,
+	.cls = &kvm_sysdev_class,
+};
+
 hpa_t bad_page_address;
 
 int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
@@ -2071,8 +2169,19 @@
 	    return r;
 
 	on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
+	r = register_cpu_notifier(&kvm_cpu_notifier);
+	if (r)
+		goto out_free_1;
 	register_reboot_notifier(&kvm_reboot_notifier);
 
+	r = sysdev_class_register(&kvm_sysdev_class);
+	if (r)
+		goto out_free_2;
+
+	r = sysdev_register(&kvm_sysdev);
+	if (r)
+		goto out_free_3;
+
 	kvm_chardev_ops.owner = module;
 
 	r = misc_register(&kvm_dev);
@@ -2084,7 +2193,13 @@
 	return r;
 
 out_free:
+	sysdev_unregister(&kvm_sysdev);
+out_free_3:
+	sysdev_class_unregister(&kvm_sysdev_class);
+out_free_2:
 	unregister_reboot_notifier(&kvm_reboot_notifier);
+	unregister_cpu_notifier(&kvm_cpu_notifier);
+out_free_1:
 	on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
 	kvm_arch_ops->hardware_unsetup();
 	return r;
@@ -2093,8 +2208,10 @@
 void kvm_exit_arch(void)
 {
 	misc_deregister(&kvm_dev);
-
+	sysdev_unregister(&kvm_sysdev);
+	sysdev_class_unregister(&kvm_sysdev_class);
 	unregister_reboot_notifier(&kvm_reboot_notifier);
+	unregister_cpu_notifier(&kvm_cpu_notifier);
 	on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
 	kvm_arch_ops->hardware_unsetup();
 	kvm_arch_ops = NULL;
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 149fa45..b6b90e9 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -443,31 +443,17 @@
 static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
 {
 	struct guest_walker walker;
-	pt_element_t guest_pte;
-	gpa_t gpa;
+	gpa_t gpa = UNMAPPED_GVA;
+	int r;
 
-	FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
-	guest_pte = *walker.ptep;
-	FNAME(release_walker)(&walker);
+	r = FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
 
-	if (!is_present_pte(guest_pte))
-		return UNMAPPED_GVA;
-
-	if (walker.level == PT_DIRECTORY_LEVEL) {
-		ASSERT((guest_pte & PT_PAGE_SIZE_MASK));
-		ASSERT(PTTYPE == 64 || is_pse(vcpu));
-
-		gpa = (guest_pte & PT_DIR_BASE_ADDR_MASK) | (vaddr &
-			(PT_LEVEL_MASK(PT_PAGE_TABLE_LEVEL) | ~PAGE_MASK));
-
-		if (PTTYPE == 32 && is_cpuid_PSE36())
-			gpa |= (guest_pte & PT32_DIR_PSE36_MASK) <<
-					(32 - PT32_DIR_PSE36_SHIFT);
-	} else {
-		gpa = (guest_pte & PT_BASE_ADDR_MASK);
-		gpa |= (vaddr & ~PAGE_MASK);
+	if (r) {
+		gpa = (gpa_t)walker.gfn << PAGE_SHIFT;
+		gpa |= vaddr & ~PAGE_MASK;
 	}
 
+	FNAME(release_walker)(&walker);
 	return gpa;
 }
 
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 85f61dd..83da4ea 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -528,7 +528,13 @@
 	save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK |
 		SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK;
 	save->cs.limit = 0xffff;
-	save->cs.base = 0xffff0000;
+	/*
+	 * cs.base should really be 0xffff0000, but vmx can't handle that, so
+	 * be consistent with it.
+	 *
+	 * Replace when we have real mode working for vmx.
+	 */
+	save->cs.base = 0xf0000;
 
 	save->gdtr.limit = 0xffff;
 	save->idtr.limit = 0xffff;
@@ -603,6 +609,10 @@
 	put_cpu();
 }
 
+static void svm_vcpu_decache(struct kvm_vcpu *vcpu)
+{
+}
+
 static void svm_cache_regs(struct kvm_vcpu *vcpu)
 {
 	vcpu->regs[VCPU_REGS_RAX] = vcpu->svm->vmcb->save.rax;
@@ -723,7 +733,7 @@
 	}
 #endif
 	vcpu->svm->cr0 = cr0;
-	vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK;
+	vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK | CR0_WP_MASK;
 	vcpu->cr0 = cr0;
 }
 
@@ -1671,6 +1681,7 @@
 
 	.vcpu_load = svm_vcpu_load,
 	.vcpu_put = svm_vcpu_put,
+	.vcpu_decache = svm_vcpu_decache,
 
 	.set_guest_debug = svm_guest_debug,
 	.get_msr = svm_get_msr,
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 27e05a7..1e640b8 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -125,6 +125,15 @@
 		per_cpu(current_vmcs, cpu) = NULL;
 }
 
+static void vcpu_clear(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->cpu != raw_smp_processor_id() && vcpu->cpu != -1)
+		smp_call_function_single(vcpu->cpu, __vcpu_clear, vcpu, 0, 1);
+	else
+		__vcpu_clear(vcpu);
+	vcpu->launched = 0;
+}
+
 static unsigned long vmcs_readl(unsigned long field)
 {
 	unsigned long value;
@@ -202,10 +211,8 @@
 
 	cpu = get_cpu();
 
-	if (vcpu->cpu != cpu) {
-		smp_call_function(__vcpu_clear, vcpu, 0, 1);
-		vcpu->launched = 0;
-	}
+	if (vcpu->cpu != cpu)
+		vcpu_clear(vcpu);
 
 	if (per_cpu(current_vmcs, cpu) != vcpu->vmcs) {
 		u8 error;
@@ -243,6 +250,11 @@
 	put_cpu();
 }
 
+static void vmx_vcpu_decache(struct kvm_vcpu *vcpu)
+{
+	vcpu_clear(vcpu);
+}
+
 static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
 {
 	return vmcs_readl(GUEST_RFLAGS);
@@ -502,7 +514,7 @@
 	return (msr & 5) == 1; /* locked but not enabled */
 }
 
-static __init void hardware_enable(void *garbage)
+static void hardware_enable(void *garbage)
 {
 	int cpu = raw_smp_processor_id();
 	u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
@@ -1375,6 +1387,11 @@
 	return 1;
 }
 
+static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+	return 0;
+}
 
 static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
 {
@@ -1635,6 +1652,7 @@
 				      struct kvm_run *kvm_run) = {
 	[EXIT_REASON_EXCEPTION_NMI]           = handle_exception,
 	[EXIT_REASON_EXTERNAL_INTERRUPT]      = handle_external_interrupt,
+	[EXIT_REASON_TRIPLE_FAULT]            = handle_triple_fault,
 	[EXIT_REASON_IO_INSTRUCTION]          = handle_io,
 	[EXIT_REASON_CR_ACCESS]               = handle_cr,
 	[EXIT_REASON_DR_ACCESS]               = handle_dr,
@@ -1786,10 +1804,10 @@
 		"kvm_vmx_return: "
 		/* Save guest registers, load host registers, keep flags */
 #ifdef CONFIG_X86_64
-		"xchg %3,     0(%%rsp) \n\t"
+		"xchg %3,     (%%rsp) \n\t"
 		"mov %%rax, %c[rax](%3) \n\t"
 		"mov %%rbx, %c[rbx](%3) \n\t"
-		"pushq 0(%%rsp); popq %c[rcx](%3) \n\t"
+		"pushq (%%rsp); popq %c[rcx](%3) \n\t"
 		"mov %%rdx, %c[rdx](%3) \n\t"
 		"mov %%rsi, %c[rsi](%3) \n\t"
 		"mov %%rdi, %c[rdi](%3) \n\t"
@@ -1804,24 +1822,24 @@
 		"mov %%r15, %c[r15](%3) \n\t"
 		"mov %%cr2, %%rax   \n\t"
 		"mov %%rax, %c[cr2](%3) \n\t"
-		"mov 0(%%rsp), %3 \n\t"
+		"mov (%%rsp), %3 \n\t"
 
 		"pop  %%rcx; pop  %%r15; pop  %%r14; pop  %%r13; pop  %%r12;"
 		"pop  %%r11; pop  %%r10; pop  %%r9;  pop  %%r8;"
 		"pop  %%rbp; pop  %%rdi; pop  %%rsi;"
 		"pop  %%rdx; pop  %%rbx; pop  %%rax \n\t"
 #else
-		"xchg %3, 0(%%esp) \n\t"
+		"xchg %3, (%%esp) \n\t"
 		"mov %%eax, %c[rax](%3) \n\t"
 		"mov %%ebx, %c[rbx](%3) \n\t"
-		"pushl 0(%%esp); popl %c[rcx](%3) \n\t"
+		"pushl (%%esp); popl %c[rcx](%3) \n\t"
 		"mov %%edx, %c[rdx](%3) \n\t"
 		"mov %%esi, %c[rsi](%3) \n\t"
 		"mov %%edi, %c[rdi](%3) \n\t"
 		"mov %%ebp, %c[rbp](%3) \n\t"
 		"mov %%cr2, %%eax  \n\t"
 		"mov %%eax, %c[cr2](%3) \n\t"
-		"mov 0(%%esp), %3 \n\t"
+		"mov (%%esp), %3 \n\t"
 
 		"pop %%ecx; popa \n\t"
 #endif
@@ -1859,9 +1877,7 @@
 	fx_restore(vcpu->host_fx_image);
 	vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0;
 
-#ifndef CONFIG_X86_64
 	asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
-#endif
 
 	/*
 	 * Profile KVM exit RIPs:
@@ -2012,6 +2028,7 @@
 
 	.vcpu_load = vmx_vcpu_load,
 	.vcpu_put = vmx_vcpu_put,
+	.vcpu_decache = vmx_vcpu_decache,
 
 	.set_guest_debug = set_guest_debug,
 	.get_msr = vmx_get_msr,
diff --git a/drivers/kvm/vmx.h b/drivers/kvm/vmx.h
index 4c0ab15..d0dc93d 100644
--- a/drivers/kvm/vmx.h
+++ b/drivers/kvm/vmx.h
@@ -180,6 +180,7 @@
 
 #define EXIT_REASON_EXCEPTION_NMI       0
 #define EXIT_REASON_EXTERNAL_INTERRUPT  1
+#define EXIT_REASON_TRIPLE_FAULT        2
 
 #define EXIT_REASON_PENDING_INTERRUPT   7
 
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 7cec6de..f729eeb 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -885,7 +885,7 @@
 	return ret;
 }
 
-static struct file_operations adb_fops = {
+static const struct file_operations adb_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= adb_read,
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index 2b8a6e8..cdd5a0f 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -121,7 +121,7 @@
 	return 0;
 }
 
-struct file_operations anslcd_fops = {
+const struct file_operations anslcd_fops = {
 	.write	= anslcd_write,
 	.ioctl	= anslcd_ioctl,
 	.open	= anslcd_open,
diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c
index 4300c62..a6d50f4 100644
--- a/drivers/macintosh/apm_emu.c
+++ b/drivers/macintosh/apm_emu.c
@@ -501,7 +501,7 @@
 	return p - buf;
 }
 
-static struct file_operations apm_bios_fops = {
+static const struct file_operations apm_bios_fops = {
 	.owner		= THIS_MODULE,
 	.read		= do_read,
 	.poll		= do_poll,
diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c
index 3079187..b195d75 100644
--- a/drivers/macintosh/nvram.c
+++ b/drivers/macintosh/nvram.c
@@ -100,7 +100,7 @@
 	return 0;
 }
 
-struct file_operations nvram_fops = {
+const struct file_operations nvram_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= nvram_llseek,
 	.read		= read_nvram,
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 6f30459..3096836 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -1277,7 +1277,7 @@
 }
 
 
-static struct file_operations smu_device_fops = {
+static const struct file_operations smu_device_fops = {
 	.llseek		= no_llseek,
 	.read		= smu_read,
 	.write		= smu_write,
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index eb6653f..96bea4b 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -2672,7 +2672,7 @@
 	return error;
 }
 
-static struct file_operations pmu_device_fops = {
+static const struct file_operations pmu_device_fops = {
 	.read		= pmu_read,
 	.write		= pmu_write,
 	.poll		= pmu_fpoll,
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 93e6ef92..4f5b6fa 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -1040,7 +1040,7 @@
 	return -EINVAL;
 }
 
-static struct file_operations pmu_device_fops = {
+static const struct file_operations pmu_device_fops = {
 	.read		= pmu_read,
 	.write		= pmu_write,
 	.ioctl		= pmu_ioctl,
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index cd6a184..b441d82 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1473,7 +1473,7 @@
 	return r;
 }
 
-static struct file_operations _ctl_fops = {
+static const struct file_operations _ctl_fops = {
 	.ioctl	 = ctl_ioctl,
 	.owner	 = THIS_MODULE,
 };
diff --git a/drivers/md/md.c b/drivers/md/md.c
index e8807ea..e85fa75 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4920,7 +4920,7 @@
 	return mask;
 }
 
-static struct file_operations md_seq_fops = {
+static const struct file_operations md_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = md_seq_open,
 	.read           = seq_read,
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index d867a6a..b8dcfa1 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -416,7 +416,7 @@
 	}
 }
 
-static struct file_operations video_fops =
+static const struct file_operations video_fops =
 {
 	.owner		= THIS_MODULE,
 	.open		= fops_open,
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index db865a0..df8d052 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -144,7 +144,7 @@
 
 
 /* File system interface */
-static struct file_operations usb_dsbr100_fops = {
+static const struct file_operations usb_dsbr100_fops = {
 	.owner =	THIS_MODULE,
 	.open =		usb_dsbr100_open,
 	.release =     	usb_dsbr100_close,
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
index c4312fa..c7c9d1d 100644
--- a/drivers/media/radio/miropcm20-radio.c
+++ b/drivers/media/radio/miropcm20-radio.c
@@ -216,7 +216,7 @@
 	.muted  = 1,
 };
 
-static struct file_operations pcm20_fops = {
+static const struct file_operations pcm20_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
index c1b1db6..c93490e 100644
--- a/drivers/media/radio/miropcm20-rds.c
+++ b/drivers/media/radio/miropcm20-rds.c
@@ -105,7 +105,7 @@
 	}
 }
 
-static struct file_operations rds_fops = {
+static const struct file_operations rds_fops = {
 	.owner		= THIS_MODULE,
 	.read		= rds_f_read,
 	.open		= rds_f_open,
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 3368a89..b2e88ad 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -358,7 +358,7 @@
 
 static struct rt_device rtrack_unit;
 
-static struct file_operations rtrack_fops = {
+static const struct file_operations rtrack_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 3ba5fa8..19d45cc 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -314,7 +314,7 @@
 
 static struct az_device aztech_unit;
 
-static struct file_operations aztech_fops = {
+static const struct file_operations aztech_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 69d4b79..8fbf0d8 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -507,7 +507,7 @@
 }
 
 
-static struct file_operations cadet_fops = {
+static const struct file_operations cadet_fops = {
 	.owner		= THIS_MODULE,
 	.open		= cadet_open,
 	.release       	= cadet_release,
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index eb14106..05e5aa7 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -346,7 +346,7 @@
 
 static int mx = 1;
 
-static struct file_operations gemtek_pci_fops = {
+static const struct file_operations gemtek_pci_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 730fe16..36c4be6 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -296,7 +296,7 @@
 
 static struct gemtek_device gemtek_unit;
 
-static struct file_operations gemtek_fops = {
+static const struct file_operations gemtek_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index e8ce5f7..9bba6eb 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -99,7 +99,7 @@
 	.remove		= __devexit_p(maestro_remove),
 };
 
-static struct file_operations maestro_fops = {
+static const struct file_operations maestro_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index c2eeae7..00a2f31 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -91,7 +91,7 @@
 static int radio_ioctl(struct inode *inode, struct file *file,
 		       unsigned int cmd, unsigned long arg);
 
-static struct file_operations maxiradio_fops = {
+static const struct file_operations maxiradio_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index b9e9848..f668387 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -262,7 +262,7 @@
 
 static struct rt_device rtrack2_unit;
 
-static struct file_operations rtrack2_fops = {
+static const struct file_operations rtrack2_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index ecc854b..f4619e4 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -265,7 +265,7 @@
 
 static struct fmi_device fmi_unit;
 
-static struct file_operations fmi_fops = {
+static const struct file_operations fmi_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 4444dce..b96fafe 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -410,7 +410,7 @@
 
 static struct fmr2_device fmr2_unit;
 
-static struct file_operations fmr2_fops = {
+static const struct file_operations fmr2_fops = {
 	.owner          = THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index f539491..d59a27a 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -338,7 +338,7 @@
 
 static struct tt_device terratec_unit;
 
-static struct file_operations terratec_fops = {
+static const struct file_operations terratec_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index bb03ad5..6d7f1e7 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -325,7 +325,7 @@
 	return video_usercopy(inode, file, cmd, arg, tr_do_ioctl);
 }
 
-static struct file_operations trust_fops = {
+static const struct file_operations trust_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index 4a72b4d..3031fef 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -318,7 +318,7 @@
 	.mutefreq	= CONFIG_RADIO_TYPHOON_MUTEFREQ,
 };
 
-static struct file_operations typhoon_fops = {
+static const struct file_operations typhoon_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 671fe1b..ec08491 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -373,7 +373,7 @@
 
 static struct zol_device zoltrix_unit;
 
-static struct file_operations zoltrix_fops =
+static const struct file_operations zoltrix_fops =
 {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 4861799..649f52f 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -742,7 +742,7 @@
  * Video4Linux Module functions
  *
  ****************************************************************************/
-static struct file_operations ar_fops = {
+static const struct file_operations ar_fops = {
 	.owner		= THIS_MODULE,
 	.open		= video_exclusive_open,
 	.release	= video_exclusive_release,
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index ab8f970..41fd09d 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -3174,7 +3174,7 @@
 	return videobuf_mmap_mapper(bttv_queue(fh),vma);
 }
 
-static struct file_operations bttv_fops =
+static const struct file_operations bttv_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = bttv_open,
@@ -3332,7 +3332,7 @@
 	return cmd.result;
 }
 
-static struct file_operations radio_fops =
+static const struct file_operations radio_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = radio_open,
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 7d0b6e5..7d47cbe 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -871,7 +871,7 @@
 	return len;
 }
 
-static struct file_operations qcam_fops = {
+static const struct file_operations qcam_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index a3989bd..925ff17 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -684,7 +684,7 @@
 }
 
 /* video device template */
-static struct file_operations qcam_fops = {
+static const struct file_operations qcam_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 3083c80..fb1410c 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -1715,7 +1715,7 @@
  * clone it for specific real devices.
  */
 
-static struct file_operations cafe_v4l_fops = {
+static const struct file_operations cafe_v4l_fops = {
 	.owner = THIS_MODULE,
 	.open = cafe_v4l_open,
 	.release = cafe_v4l_release,
@@ -1969,7 +1969,7 @@
 			s - cafe_debug_buf);
 }
 
-static struct file_operations cafe_dfs_reg_ops = {
+static const struct file_operations cafe_dfs_reg_ops = {
 	.owner = THIS_MODULE,
 	.read = cafe_dfs_read_regs,
 	.open = cafe_dfs_open
@@ -1995,7 +1995,7 @@
 			s - cafe_debug_buf);
 }
 
-static struct file_operations cafe_dfs_cam_ops = {
+static const struct file_operations cafe_dfs_cam_ops = {
 	.owner = THIS_MODULE,
 	.read = cafe_dfs_read_cam,
 	.open = cafe_dfs_open
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 3b31a0d..7e8d5ef 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -3791,7 +3791,7 @@
 	return 0;
 }
 
-static struct file_operations cpia_fops = {
+static const struct file_operations cpia_fops = {
 	.owner		= THIS_MODULE,
 	.open		= cpia_open,
 	.release       	= cpia_close,
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index d09f499..1bda7ad 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -1924,7 +1924,7 @@
 /***
  * The v4l video device structure initialized for this device
  ***/
-static struct file_operations fops_template = {
+static const struct file_operations fops_template = {
 	.owner		= THIS_MODULE,
 	.open		= cpia2_open,
 	.release	= cpia2_close,
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 0cf0360..9a7a299 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1051,7 +1051,7 @@
 	return videobuf_mmap_mapper(&fh->mpegq, vma);
 }
 
-static struct file_operations mpeg_fops =
+static const struct file_operations mpeg_fops =
 {
 	.owner	       = THIS_MODULE,
 	.open	       = mpeg_open,
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 8613378..c86a7e0 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1808,7 +1808,7 @@
 /* ----------------------------------------------------------- */
 /* exported stuff                                              */
 
-static struct file_operations video_fops =
+static const struct file_operations video_fops =
 {
 	.owner	       = THIS_MODULE,
 	.open	       = video_open,
@@ -1839,7 +1839,7 @@
 	.minor         = -1,
 };
 
-static struct file_operations radio_fops =
+static const struct file_operations radio_fops =
 {
 	.owner         = THIS_MODULE,
 	.open          = video_open,
diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
index 917021f..ff4b238 100644
--- a/drivers/media/video/dabusb.c
+++ b/drivers/media/video/dabusb.c
@@ -696,7 +696,7 @@
 	return ret;
 }
 
-static struct file_operations dabusb_fops =
+static const struct file_operations dabusb_fops =
 {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 36e72c2..bec6760 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1480,7 +1480,7 @@
 	return ret;
 }
 
-static struct file_operations em28xx_v4l_fops = {
+static const struct file_operations em28xx_v4l_fops = {
 	.owner = THIS_MODULE,
 	.open = em28xx_v4l2_open,
 	.release = em28xx_v4l2_close,
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 86e353b..49792ae 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -2454,7 +2454,7 @@
 }
 
 
-static struct file_operations et61x251_fops = {
+static const struct file_operations et61x251_fops = {
 	.owner = THIS_MODULE,
 	.open =    et61x251_open,
 	.release = et61x251_release,
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 616a35d..9528e10 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1748,7 +1748,7 @@
 	return 0;
 }
 
-static struct file_operations meye_fops = {
+static const struct file_operations meye_fops = {
 	.owner		= THIS_MODULE,
 	.open		= meye_open,
 	.release	= meye_release,
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index b4db2cb..e5edff1 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -4653,7 +4653,7 @@
 	return 0;
 }
 
-static struct file_operations ov511_fops = {
+static const struct file_operations ov511_fops = {
 	.owner =	THIS_MODULE,
 	.open =		ov51x_v4l1_open,
 	.release =	ov51x_v4l1_close,
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 5d681fa..d38d3dc 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -881,7 +881,7 @@
 	return len;
 }
 
-static struct file_operations pms_fops = {
+static const struct file_operations pms_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index bb40e90..6cf1708 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -986,7 +986,7 @@
 }
 
 
-static struct file_operations vdev_fops = {
+static const struct file_operations vdev_fops = {
 	.owner      = THIS_MODULE,
 	.open       = pvr2_v4l2_open,
 	.release    = pvr2_v4l2_release,
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index a996aad..9825fd3 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -152,7 +152,7 @@
 			    unsigned int ioctlnr, unsigned long arg);
 static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
 
-static struct file_operations pwc_fops = {
+static const struct file_operations pwc_fops = {
 	.owner =	THIS_MODULE,
 	.open =		pwc_video_open,
 	.release =     	pwc_video_close,
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index 77bb940..0b5d159 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -817,7 +817,7 @@
 module_init(init_saa_5246a);
 module_exit(cleanup_saa_5246a);
 
-static struct file_operations saa_fops = {
+static const struct file_operations saa_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = saa5246a_open,
 	.release = saa5246a_release,
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index bb3fb43..3e84737 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -699,7 +699,7 @@
 module_init(init_saa_5249);
 module_exit(cleanup_saa_5249);
 
-static struct file_operations saa_fops = {
+static const struct file_operations saa_fops = {
 	.owner		= THIS_MODULE,
 	.open		= saa5249_open,
 	.release       	= saa5249_release,
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index daaae87..f521603 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -319,7 +319,7 @@
 	return video_usercopy(inode, file, cmd, arg, ts_do_ioctl);
 }
 
-static struct file_operations ts_fops =
+static const struct file_operations ts_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = ts_open,
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index bfcb860..72444f0 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -563,7 +563,7 @@
 	return mask;
 }
 
-struct file_operations saa7134_dsp_fops = {
+const struct file_operations saa7134_dsp_fops = {
 	.owner   = THIS_MODULE,
 	.open    = dsp_open,
 	.release = dsp_release,
@@ -804,7 +804,7 @@
 	}
 }
 
-struct file_operations saa7134_mixer_fops = {
+const struct file_operations saa7134_mixer_fops = {
 	.owner   = THIS_MODULE,
 	.open    = mixer_open,
 	.release = mixer_release,
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 830617e..f2cb630 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -2336,7 +2336,7 @@
 	return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
 }
 
-static struct file_operations video_fops =
+static const struct file_operations video_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = video_open,
@@ -2349,7 +2349,7 @@
 	.llseek   = no_llseek,
 };
 
-static struct file_operations radio_fops =
+static const struct file_operations radio_fops =
 {
 	.owner	  = THIS_MODULE,
 	.open	  = video_open,
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index e88ad7b..88cd129 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -683,8 +683,8 @@
 /* ----------------------------------------------------------- */
 /* saa7134-oss.c                                               */
 
-extern struct file_operations saa7134_dsp_fops;
-extern struct file_operations saa7134_mixer_fops;
+extern const struct file_operations saa7134_dsp_fops;
+extern const struct file_operations saa7134_mixer_fops;
 
 int saa7134_oss_init1(struct saa7134_dev *dev);
 int saa7134_oss_fini(struct saa7134_dev *dev);
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
index 7aeec57..038448f 100644
--- a/drivers/media/video/se401.c
+++ b/drivers/media/video/se401.c
@@ -1185,7 +1185,7 @@
 	return 0;
 }
 
-static struct file_operations se401_fops = {
+static const struct file_operations se401_fops = {
 	.owner =	THIS_MODULE,
 	.open =         se401_open,
 	.release =      se401_close,
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 18458d4..04d4c8f 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -2736,7 +2736,7 @@
 
 /*****************************************************************************/
 
-static struct file_operations sn9c102_fops = {
+static const struct file_operations sn9c102_fops = {
 	.owner = THIS_MODULE,
 	.open =    sn9c102_open,
 	.release = sn9c102_release,
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 525d812..3e736be 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -1901,7 +1901,7 @@
 	return 0;
 }
 
-static struct file_operations saa_fops = {
+static const struct file_operations saa_fops = {
 	.owner = THIS_MODULE,
 	.open = saa_open,
 	.release = saa_release,
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index a1ec3ac..bf3aa8d 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -1380,7 +1380,7 @@
 	return realcount;
 }				/* stv680_read */
 
-static struct file_operations stv680_fops = {
+static const struct file_operations stv680_fops = {
 	.owner =	THIS_MODULE,
 	.open =		stv_open,
 	.release =     	stv_close,
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 1654576..e2747bd 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -228,7 +228,7 @@
 	.detach_client   = tvmixer_clients,
 };
 
-static struct file_operations tvmixer_fops = {
+static const struct file_operations tvmixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek         = no_llseek,
 	.ioctl          = tvmixer_ioctl,
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index b560c9d..d34d8c8 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -945,7 +945,7 @@
 	return rv;
 }
 
-static struct file_operations usbvideo_fops = {
+static const struct file_operations usbvideo_fops = {
 	.owner =  THIS_MODULE,
 	.open =   usbvideo_v4l_open,
 	.release =usbvideo_v4l_close,
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
index 08f9559..876fd27 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -1234,7 +1234,7 @@
 static inline void vicam_destroy_proc_entry(void *ptr) { }
 #endif
 
-static struct file_operations vicam_fops = {
+static const struct file_operations vicam_fops = {
 	.owner		= THIS_MODULE,
 	.open		= vicam_open,
 	.release	= vicam_close,
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index bdd6301..4eb7330 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1475,7 +1475,7 @@
 //
 
 // Video template
-static struct file_operations usbvision_fops = {
+static const struct file_operations usbvision_fops = {
 	.owner             = THIS_MODULE,
 	.open		= usbvision_v4l2_open,
 	.release	= usbvision_v4l2_close,
@@ -1496,7 +1496,7 @@
 
 
 // Radio template
-static struct file_operations usbvision_radio_fops = {
+static const struct file_operations usbvision_radio_fops = {
 	.owner             = THIS_MODULE,
 	.open		= usbvision_radio_open,
 	.release	= usbvision_radio_close,
@@ -1517,7 +1517,7 @@
 
 
 // vbi template
-static struct file_operations usbvision_vbi_fops = {
+static const struct file_operations usbvision_vbi_fops = {
 	.owner             = THIS_MODULE,
 	.open		= usbvision_vbi_open,
 	.release	= usbvision_vbi_close,
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 6a0e8ca..30c3822 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -1561,7 +1561,7 @@
 }
 
 
-static struct file_operations video_fops;
+static const struct file_operations video_fops;
 
 /**
  *	video_register_device - register video4linux devices
@@ -1709,7 +1709,7 @@
 /*
  * Video fs operations
  */
-static struct file_operations video_fops=
+static const struct file_operations video_fops=
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index a373c14..0c658b7 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -4390,7 +4390,7 @@
 // __initdata
 static int vino_init_stage = 0;
 
-static struct file_operations vino_fops = {
+static const struct file_operations vino_fops = {
 	.owner		= THIS_MODULE,
 	.open		= vino_open,
 	.release	= vino_close,
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index d4cf556..cfb6b1f 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -1292,7 +1292,7 @@
 	return ret;
 }
 
-static struct file_operations vivi_fops = {
+static const struct file_operations vivi_fops = {
 	.owner		= THIS_MODULE,
 	.open           = vivi_open,
 	.release        = vivi_release,
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index 8d14f30..4736640 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -183,7 +183,7 @@
 static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
 			      size_t count, loff_t *ppos);
 
-static struct file_operations w9966_fops = {
+static const struct file_operations w9966_fops = {
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 9f403af..6e64af2 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -399,7 +399,7 @@
  ****************************************************************************/
 
 /* Video4linux interface */
-static struct file_operations w9968cf_fops;
+static const struct file_operations w9968cf_fops;
 static int w9968cf_open(struct inode*, struct file*);
 static int w9968cf_release(struct inode*, struct file*);
 static int w9968cf_mmap(struct file*, struct vm_area_struct*);
@@ -3466,7 +3466,7 @@
 }
 
 
-static struct file_operations w9968cf_fops = {
+static const struct file_operations w9968cf_fops = {
 	.owner =   THIS_MODULE,
 	.open =    w9968cf_open,
 	.release = w9968cf_release,
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 52d0f75..8da7f15 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -1871,7 +1871,7 @@
 }
 
 
-static struct file_operations zc0301_fops = {
+static const struct file_operations zc0301_fops = {
 	.owner =   THIS_MODULE,
 	.open =    zc0301_open,
 	.release = zc0301_release,
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index e10a9ee..0743237 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -4679,7 +4679,7 @@
 	return 0;
 }
 
-static struct file_operations zoran_fops = {
+static const struct file_operations zoran_fops = {
 	.owner = THIS_MODULE,
 	.open = zoran_open,
 	.release = zoran_close,
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c
index c374c76..446ae8d 100644
--- a/drivers/media/video/zoran_procfs.c
+++ b/drivers/media/video/zoran_procfs.c
@@ -186,7 +186,7 @@
 	return count;
 }
 
-static struct file_operations zoran_operations = {
+static const struct file_operations zoran_operations = {
 	.open		= zoran_open,
 	.read		= seq_read,
 	.write		= zoran_write,
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index b0b8042..9d0f304 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -2662,7 +2662,7 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
-static struct file_operations mptctl_fops = {
+static const struct file_operations mptctl_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.release =	mptctl_release,
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index e33d446..8ba275a 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -1111,7 +1111,7 @@
 	return 0;
 }
 
-static struct file_operations config_fops = {
+static const struct file_operations config_fops = {
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 	.ioctl = i2o_cfg_ioctl,
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index a61cb17..06892ac 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -1703,133 +1703,133 @@
 	return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data);
 };
 
-static struct file_operations i2o_seq_fops_lct = {
+static const struct file_operations i2o_seq_fops_lct = {
 	.open = i2o_seq_open_lct,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_hrt = {
+static const struct file_operations i2o_seq_fops_hrt = {
 	.open = i2o_seq_open_hrt,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_status = {
+static const struct file_operations i2o_seq_fops_status = {
 	.open = i2o_seq_open_status,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_hw = {
+static const struct file_operations i2o_seq_fops_hw = {
 	.open = i2o_seq_open_hw,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_ddm_table = {
+static const struct file_operations i2o_seq_fops_ddm_table = {
 	.open = i2o_seq_open_ddm_table,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_driver_store = {
+static const struct file_operations i2o_seq_fops_driver_store = {
 	.open = i2o_seq_open_driver_store,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_drivers_stored = {
+static const struct file_operations i2o_seq_fops_drivers_stored = {
 	.open = i2o_seq_open_drivers_stored,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_groups = {
+static const struct file_operations i2o_seq_fops_groups = {
 	.open = i2o_seq_open_groups,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_phys_device = {
+static const struct file_operations i2o_seq_fops_phys_device = {
 	.open = i2o_seq_open_phys_device,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_claimed = {
+static const struct file_operations i2o_seq_fops_claimed = {
 	.open = i2o_seq_open_claimed,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_users = {
+static const struct file_operations i2o_seq_fops_users = {
 	.open = i2o_seq_open_users,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_priv_msgs = {
+static const struct file_operations i2o_seq_fops_priv_msgs = {
 	.open = i2o_seq_open_priv_msgs,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_authorized_users = {
+static const struct file_operations i2o_seq_fops_authorized_users = {
 	.open = i2o_seq_open_authorized_users,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_dev_name = {
+static const struct file_operations i2o_seq_fops_dev_name = {
 	.open = i2o_seq_open_dev_name,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_dev_identity = {
+static const struct file_operations i2o_seq_fops_dev_identity = {
 	.open = i2o_seq_open_dev_identity,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_ddm_identity = {
+static const struct file_operations i2o_seq_fops_ddm_identity = {
 	.open = i2o_seq_open_ddm_identity,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_uinfo = {
+static const struct file_operations i2o_seq_fops_uinfo = {
 	.open = i2o_seq_open_uinfo,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_sgl_limits = {
+static const struct file_operations i2o_seq_fops_sgl_limits = {
 	.open = i2o_seq_open_sgl_limits,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
 
-static struct file_operations i2o_seq_fops_sensors = {
+static const struct file_operations i2o_seq_fops_sensors = {
 	.open = i2o_seq_open_sensors,
 	.read = seq_read,
 	.llseek = seq_lseek,
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
index 11a801b..ca86f11 100644
--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
+++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
@@ -169,7 +169,7 @@
 /*
  *	The various file operations we support.
  */
-static struct file_operations cpustate_fops = {
+static const struct file_operations cpustate_fops = {
       owner:THIS_MODULE,
       open:cpustate_open,
       release:cpustate_release,
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index b99dc50..c436d3d 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -156,7 +156,7 @@
 static struct dentry *ibmasmfs_create_file (struct super_block *sb,
 			struct dentry *parent,
 		       	const char *name,
-			struct file_operations *fops,
+			const struct file_operations *fops,
 			void *data,
 			int mode)
 {
@@ -581,28 +581,28 @@
 	return count;
 }
 
-static struct file_operations command_fops = {
+static const struct file_operations command_fops = {
 	.open =		command_file_open,
 	.release =	command_file_close,
 	.read =		command_file_read,
 	.write =	command_file_write,
 };
 
-static struct file_operations event_fops = {
+static const struct file_operations event_fops = {
 	.open =		event_file_open,
 	.release =	event_file_close,
 	.read =		event_file_read,
 	.write =	event_file_write,
 };
 
-static struct file_operations r_heartbeat_fops = {
+static const struct file_operations r_heartbeat_fops = {
 	.open =		r_heartbeat_file_open,
 	.release =	r_heartbeat_file_close,
 	.read =		r_heartbeat_file_read,
 	.write =	r_heartbeat_file_write,
 };
 
-static struct file_operations remote_settings_fops = {
+static const struct file_operations remote_settings_fops = {
 	.open =		remote_settings_file_open,
 	.release =	remote_settings_file_close,
 	.read =		remote_settings_file_read,
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3013d08..61a994e 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -759,7 +759,7 @@
 	return ret;
 } /* memory_ioctl */
 
-static struct file_operations mtd_fops = {
+static const struct file_operations mtd_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= mtd_lseek,
 	.read		= mtd_read,
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index aa9dd8f..4218075 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -338,7 +338,8 @@
 }
 
 #if defined(CONFIG_ARCNET_COM20020_PCI_MODULE) || \
-    defined(CONFIG_ARCNET_COM20020_ISA_MODULE)
+    defined(CONFIG_ARCNET_COM20020_ISA_MODULE) || \
+    defined(CONFIG_ARCNET_COM20020_CS_MODULE)
 EXPORT_SYMBOL(com20020_check);
 EXPORT_SYMBOL(com20020_found);
 #endif
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 8ce8fec..61a6fa4 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3120,7 +3120,7 @@
 	return res;
 }
 
-static struct file_operations bond_info_fops = {
+static const struct file_operations bond_info_fops = {
 	.owner   = THIS_MODULE,
 	.open    = bond_info_open,
 	.read    = seq_read,
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 5b788d8..d254269 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -459,7 +459,7 @@
 	return seq_open(file, &bpq_seqops);
 }
 
-static struct file_operations bpq_info_fops = {
+static const struct file_operations bpq_info_fops = {
 	.owner = THIS_MODULE,
 	.open = bpq_info_open,
 	.read = seq_read,
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 2ce047e..6fdaad5 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -2083,7 +2083,7 @@
 	return seq_open(file, &scc_net_seq_ops);
 }
 
-static struct file_operations scc_net_seq_fops = {
+static const struct file_operations scc_net_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = scc_net_seq_open,
 	.read	 = seq_read,
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 6d74f08..08f2711 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -804,7 +804,7 @@
 	return seq_open(file, &yam_seqops);
 }
 
-static struct file_operations yam_info_fops = {
+static const struct file_operations yam_info_fops = {
 	.owner = THIS_MODULE,
 	.open = yam_info_open,
 	.read = seq_read,
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 99343b5..458db05 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -1156,7 +1156,7 @@
 	return rc;
 }
 
-static struct file_operations ibmveth_proc_fops = {
+static const struct file_operations ibmveth_proc_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ibmveth_proc_open,
 	.read    = seq_read,
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index e2b1af6..3457e9d 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -385,7 +385,7 @@
 	return single_open(file, vlsi_seq_show, PDE(inode)->data);
 }
 
-static struct file_operations vlsi_proc_fops = {
+static const struct file_operations vlsi_proc_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = vlsi_seq_open,
 	.read    = seq_read,
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 0986f6c..11b575f 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -834,7 +834,7 @@
 	return err;
 }
 
-static struct file_operations ppp_device_fops = {
+static const struct file_operations ppp_device_fops = {
 	.owner		= THIS_MODULE,
 	.read		= ppp_read,
 	.write		= ppp_write,
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 315d5c3..860bb0f 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -1043,7 +1043,7 @@
 	return seq_open(file, &pppoe_seq_ops);
 }
 
-static struct file_operations pppoe_seq_fops = {
+static const struct file_operations pppoe_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= pppoe_seq_open,
 	.read		= seq_read,
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 151a2e1..5643d1e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -744,7 +744,7 @@
 	return 0;
 }
 
-static struct file_operations tun_fops = {
+static const struct file_operations tun_fops = {
 	.owner	= THIS_MODULE,
 	.llseek = no_llseek,
 	.read  = do_sync_read,
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 6c7dfb5..e91b5a8 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -311,7 +311,7 @@
 static int cosa_fasync(struct inode *inode, struct file *file, int on);
 #endif
 
-static struct file_operations cosa_fops = {
+static const struct file_operations cosa_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= cosa_read,
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 44a2270..b08055a 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4430,53 +4430,53 @@
 static int proc_config_open( struct inode *inode, struct file *file );
 static int proc_wepkey_open( struct inode *inode, struct file *file );
 
-static struct file_operations proc_statsdelta_ops = {
+static const struct file_operations proc_statsdelta_ops = {
 	.read		= proc_read,
 	.open		= proc_statsdelta_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_stats_ops = {
+static const struct file_operations proc_stats_ops = {
 	.read		= proc_read,
 	.open		= proc_stats_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_status_ops = {
+static const struct file_operations proc_status_ops = {
 	.read		= proc_read,
 	.open		= proc_status_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_SSID_ops = {
+static const struct file_operations proc_SSID_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_SSID_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_BSSList_ops = {
+static const struct file_operations proc_BSSList_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_BSSList_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_APList_ops = {
+static const struct file_operations proc_APList_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_APList_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_config_ops = {
+static const struct file_operations proc_config_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_config_open,
 	.release	= proc_close
 };
 
-static struct file_operations proc_wepkey_ops = {
+static const struct file_operations proc_wepkey_ops = {
 	.read		= proc_read,
 	.write		= proc_write,
 	.open		= proc_wepkey_open,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index b9df06a..35dbe45 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -355,37 +355,37 @@
 #undef fappend
 
 
-static struct file_operations devinfo_fops = {
+static const struct file_operations devinfo_fops = {
 	.read = devinfo_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations spromdump_fops = {
+static const struct file_operations spromdump_fops = {
 	.read = spromdump_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations drvinfo_fops = {
+static const struct file_operations drvinfo_fops = {
 	.read = drvinfo_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations tsf_fops = {
+static const struct file_operations tsf_fops = {
 	.read = tsf_read_file,
 	.write = tsf_write_file,
 	.open = open_file_generic,
 };
 
-static struct file_operations txstat_fops = {
+static const struct file_operations txstat_fops = {
 	.read = txstat_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations restart_fops = {
+static const struct file_operations restart_fops = {
 	.write = restart_write_file,
 	.open = open_file_generic,
 };
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index ce3a8ba..f5ce1c6 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1160,7 +1160,7 @@
 	return seq_open(file, &strip_seq_ops);
 }
 
-static struct file_operations strip_seq_fops = {
+static const struct file_operations strip_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = strip_seq_open,
 	.read    = seq_read,
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index 04d6417..00e937e 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -181,7 +181,7 @@
 	return retval;
 }
  
-struct file_operations event_buffer_fops = {
+const struct file_operations event_buffer_fops = {
 	.open		= event_buffer_open,
 	.release	= event_buffer_release,
 	.read		= event_buffer_read,
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h
index 9241627..9b6a4eb 100644
--- a/drivers/oprofile/event_buffer.h
+++ b/drivers/oprofile/event_buffer.h
@@ -41,7 +41,7 @@
 /* add data to the event buffer */
 void add_event_entry(unsigned long data);
  
-extern struct file_operations event_buffer_fops;
+extern const struct file_operations event_buffer_fops;
  
 /* mutex between sync_cpu_buffers() and the
  * file reading code.
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index a72006c..ef953ba 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -44,7 +44,7 @@
 }
 
 
-static struct file_operations depth_fops = {
+static const struct file_operations depth_fops = {
 	.read		= depth_read,
 	.write		= depth_write
 };
@@ -56,7 +56,7 @@
 }
 
 
-static struct file_operations pointer_size_fops = {
+static const struct file_operations pointer_size_fops = {
 	.read		= pointer_size_read,
 };
 
@@ -67,7 +67,7 @@
 }
  
  
-static struct file_operations cpu_type_fops = {
+static const struct file_operations cpu_type_fops = {
 	.read		= cpu_type_read,
 };
  
@@ -101,7 +101,7 @@
 }
 
  
-static struct file_operations enable_fops = {
+static const struct file_operations enable_fops = {
 	.read		= enable_read,
 	.write		= enable_write,
 };
@@ -114,7 +114,7 @@
 }
 
 
-static struct file_operations dump_fops = {
+static const struct file_operations dump_fops = {
 	.write		= dump_write,
 };
  
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index 5756401..6e67b42 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -115,14 +115,14 @@
 }
 
 
-static struct file_operations ulong_fops = {
+static const struct file_operations ulong_fops = {
 	.read		= ulong_read_file,
 	.write		= ulong_write_file,
 	.open		= default_open,
 };
 
 
-static struct file_operations ulong_ro_fops = {
+static const struct file_operations ulong_ro_fops = {
 	.read		= ulong_read_file,
 	.open		= default_open,
 };
@@ -182,7 +182,7 @@
 }
  
 
-static struct file_operations atomic_ro_fops = {
+static const struct file_operations atomic_ro_fops = {
 	.read		= atomic_read_file,
 	.open		= default_open,
 };
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index fe3f5f5..894fdb9 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -1091,7 +1091,7 @@
 	return single_open(file, &ccio_proc_info, NULL);
 }
 
-static struct file_operations ccio_proc_info_fops = {
+static const struct file_operations ccio_proc_info_fops = {
 	.owner = THIS_MODULE,
 	.open = ccio_proc_info_open,
 	.read = seq_read,
@@ -1127,7 +1127,7 @@
 	return single_open(file, &ccio_proc_bitmap_info, NULL);
 }
 
-static struct file_operations ccio_proc_bitmap_fops = {
+static const struct file_operations ccio_proc_bitmap_fops = {
 	.owner = THIS_MODULE,
 	.open = ccio_proc_bitmap_open,
 	.read = seq_read,
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index e13aafa..86e9c84 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -97,7 +97,7 @@
 /*
  *	The various file operations we support.
  */
-static struct file_operations eisa_eeprom_fops = {
+static const struct file_operations eisa_eeprom_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	eisa_eeprom_llseek,
 	.read =		eisa_eeprom_read,
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index f1e7ccd..76a29da 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -1799,7 +1799,7 @@
 	return single_open(f, &sba_proc_info, NULL);
 }
 
-static struct file_operations sba_proc_fops = {
+static const struct file_operations sba_proc_fops = {
 	.owner = THIS_MODULE,
 	.open = sba_proc_open,
 	.read = seq_read,
@@ -1831,7 +1831,7 @@
 	return single_open(f, &sba_proc_bitmap_info, NULL);
 }
 
-static struct file_operations sba_proc_bitmap_fops = {
+static const struct file_operations sba_proc_bitmap_fops = {
 	.owner = THIS_MODULE,
 	.open = sba_proc_bitmap_open,
 	.read = seq_read,
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 634f74d..a13abf5 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -202,7 +202,7 @@
 	return 0;
 }
 
-static struct file_operations debug_ops = {
+static const struct file_operations debug_ops = {
 	.owner = THIS_MODULE,
 	.open = open,
 	.llseek = lseek,
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 4a6760a..ed87aa5 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -287,7 +287,7 @@
 }
 #endif /* HAVE_PCI_MMAP */
 
-static struct file_operations proc_bus_pci_operations = {
+static const struct file_operations proc_bus_pci_operations = {
 	.llseek		= proc_bus_pci_lseek,
 	.read		= proc_bus_pci_read,
 	.write		= proc_bus_pci_write,
@@ -456,7 +456,7 @@
 {
 	return seq_open(file, &proc_bus_pci_devices_op);
 }
-static struct file_operations proc_bus_pci_dev_operations = {
+static const struct file_operations proc_bus_pci_dev_operations = {
 	.open		= proc_bus_pci_dev_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 8849414..27523c5 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -765,7 +765,7 @@
 
 /*====================================================================*/
 
-static struct file_operations ds_fops = {
+static const struct file_operations ds_fops = {
 	.owner		= THIS_MODULE,
 	.open		= ds_open,
 	.release	= ds_release,
diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
index d21f3c1..40b724e 100644
--- a/drivers/pnp/isapnp/proc.c
+++ b/drivers/pnp/isapnp/proc.c
@@ -85,7 +85,7 @@
 	return nbytes;
 }
 
-static struct file_operations isapnp_proc_bus_file_operations =
+static const struct file_operations isapnp_proc_bus_file_operations =
 {
 	.llseek		= isapnp_proc_bus_lseek,
 	.read		= isapnp_proc_bus_read,
diff --git a/drivers/ps3/Makefile b/drivers/ps3/Makefile
index d547cf5..96958c0 100644
--- a/drivers/ps3/Makefile
+++ b/drivers/ps3/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_PS3_VUART) += vuart.o
+obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
new file mode 100644
index 0000000..1926b4d
--- /dev/null
+++ b/drivers/ps3/ps3av.c
@@ -0,0 +1,974 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * AV backend support for PS3
+ *
+ * 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 of the License.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/kernel.h>
+#include <linux/ioctl.h>
+#include <asm/lv1call.h>
+#include <asm/ps3av.h>
+#include <asm/ps3.h>
+
+#include "vuart.h"
+
+#define BUFSIZE          4096	/* vuart buf size */
+#define PS3AV_BUF_SIZE   512	/* max packet size */
+
+static int timeout = 5000;	/* in msec ( 5 sec ) */
+module_param(timeout, int, 0644);
+
+static struct ps3av ps3av;
+
+static struct ps3_vuart_port_device ps3av_dev = {
+	.match_id = PS3_MATCH_ID_AV_SETTINGS
+};
+
+/* color space */
+#define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8
+#define RGB8   PS3AV_CMD_VIDEO_CS_RGB_8
+/* format */
+#define XRGB   PS3AV_CMD_VIDEO_FMT_X8R8G8B8
+/* aspect */
+#define A_N    PS3AV_CMD_AV_ASPECT_4_3
+#define A_W    PS3AV_CMD_AV_ASPECT_16_9
+static const struct avset_video_mode {
+	u32 cs;
+	u32 fmt;
+	u32 vid;
+	u32 aspect;
+	u32 x;
+	u32 y;
+	u32 interlace;
+	u32 freq;
+} video_mode_table[] = {
+	{     0, }, /* auto */
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I,       A_N,  720,  480, 1, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P,       A_N,  720,  480, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ,  A_N, 1280,  720, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I,       A_N,  720,  576, 1, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P,       A_N,  720,  576, 0, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ,  A_N, 1280,  720, 0, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA,       A_W, 1280,  768, 0, 60},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA,       A_N, 1280, 1024, 0, 60},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA,      A_W, 1920, 1200, 0, 60},
+};
+
+/* supported CIDs */
+static u32 cmd_table[] = {
+	/* init */
+	PS3AV_CID_AV_INIT,
+	PS3AV_CID_AV_FIN,
+	PS3AV_CID_VIDEO_INIT,
+	PS3AV_CID_AUDIO_INIT,
+
+	/* set */
+	PS3AV_CID_AV_ENABLE_EVENT,
+	PS3AV_CID_AV_DISABLE_EVENT,
+
+	PS3AV_CID_AV_VIDEO_CS,
+	PS3AV_CID_AV_VIDEO_MUTE,
+	PS3AV_CID_AV_VIDEO_DISABLE_SIG,
+	PS3AV_CID_AV_AUDIO_PARAM,
+	PS3AV_CID_AV_AUDIO_MUTE,
+	PS3AV_CID_AV_HDMI_MODE,
+	PS3AV_CID_AV_TV_MUTE,
+
+	PS3AV_CID_VIDEO_MODE,
+	PS3AV_CID_VIDEO_FORMAT,
+	PS3AV_CID_VIDEO_PITCH,
+
+	PS3AV_CID_AUDIO_MODE,
+	PS3AV_CID_AUDIO_MUTE,
+	PS3AV_CID_AUDIO_ACTIVE,
+	PS3AV_CID_AUDIO_INACTIVE,
+	PS3AV_CID_AVB_PARAM,
+
+	/* get */
+	PS3AV_CID_AV_GET_HW_CONF,
+	PS3AV_CID_AV_GET_MONITOR_INFO,
+
+	/* event */
+	PS3AV_CID_EVENT_UNPLUGGED,
+	PS3AV_CID_EVENT_PLUGGED,
+	PS3AV_CID_EVENT_HDCP_DONE,
+	PS3AV_CID_EVENT_HDCP_FAIL,
+	PS3AV_CID_EVENT_HDCP_AUTH,
+	PS3AV_CID_EVENT_HDCP_ERROR,
+
+	0
+};
+
+#define PS3AV_EVENT_CMD_MASK           0x10000000
+#define PS3AV_EVENT_ID_MASK            0x0000ffff
+#define PS3AV_CID_MASK                 0xffffffff
+#define PS3AV_REPLY_BIT                0x80000000
+
+#define ps3av_event_get_port_id(cid)   ((cid >> 16) & 0xff)
+
+static u32 *ps3av_search_cmd_table(u32 cid, u32 mask)
+{
+	u32 *table;
+	int i;
+
+	table = cmd_table;
+	for (i = 0;; table++, i++) {
+		if ((*table & mask) == (cid & mask))
+			break;
+		if (*table == 0)
+			return NULL;
+	}
+	return table;
+}
+
+static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr)
+{
+	u32 *table;
+
+	if (hdr->cid & PS3AV_EVENT_CMD_MASK) {
+		table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK);
+		if (table)
+			dev_dbg(&ps3av_dev.core,
+				"recv event packet cid:%08x port:0x%x size:%d\n",
+				hdr->cid, ps3av_event_get_port_id(hdr->cid),
+				hdr->size);
+		else
+			printk(KERN_ERR
+			       "%s: failed event packet, cid:%08x size:%d\n",
+			       __FUNCTION__, hdr->cid, hdr->size);
+		return 1;	/* receive event packet */
+	}
+	return 0;
+}
+
+static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf,
+			      struct ps3av_reply_hdr *recv_buf, int write_len,
+			      int read_len)
+{
+	int res;
+	u32 cmd;
+	int event;
+
+	if (!ps3av.available)
+		return -ENODEV;
+
+	/* send pkt */
+	res = ps3av_vuart_write(ps3av.dev, send_buf, write_len);
+	if (res < 0) {
+		dev_dbg(&ps3av_dev.core,
+			"%s: ps3av_vuart_write() failed (result=%d)\n",
+			__FUNCTION__, res);
+		return res;
+	}
+
+	/* recv pkt */
+	cmd = send_buf->cid;
+	do {
+		/* read header */
+		res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE,
+				       timeout);
+		if (res != PS3AV_HDR_SIZE) {
+			dev_dbg(&ps3av_dev.core,
+				"%s: ps3av_vuart_read() failed (result=%d)\n",
+				__FUNCTION__, res);
+			return res;
+		}
+
+		/* read body */
+		res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid,
+				       recv_buf->size, timeout);
+		if (res < 0) {
+			dev_dbg(&ps3av_dev.core,
+				"%s: ps3av_vuart_read() failed (result=%d)\n",
+				__FUNCTION__, res);
+			return res;
+		}
+		res += PS3AV_HDR_SIZE;	/* total len */
+		event = ps3av_parse_event_packet(recv_buf);
+		/* ret > 0 event packet */
+	} while (event);
+
+	if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) {
+		dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n",
+			__FUNCTION__, recv_buf->cid);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf,
+				      const struct ps3av_reply_hdr *recv_buf,
+				      int user_buf_size)
+{
+	int return_len;
+
+	if (recv_buf->version != PS3AV_VERSION) {
+		dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n",
+			recv_buf->version);
+		return -EFAULT;
+	}
+	return_len = recv_buf->size + PS3AV_HDR_SIZE;
+	if (return_len > user_buf_size)
+		return_len = user_buf_size;
+	memcpy(cmd_buf, recv_buf, return_len);
+	return 0;		/* success */
+}
+
+void ps3av_set_hdr(u32 cid, u16 size, struct ps3av_send_hdr *hdr)
+{
+	hdr->version = PS3AV_VERSION;
+	hdr->size = size - PS3AV_HDR_SIZE;
+	hdr->cid = cid;
+}
+
+int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size,
+		 struct ps3av_send_hdr *buf)
+{
+	int res = 0;
+	union {
+		struct ps3av_reply_hdr reply_hdr;
+		u8 raw[PS3AV_BUF_SIZE];
+	} recv_buf;
+
+	u32 *table;
+
+	BUG_ON(!ps3av.available);
+
+	if (down_interruptible(&ps3av.sem))
+		return -ERESTARTSYS;
+
+	table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK);
+	BUG_ON(!table);
+	BUG_ON(send_len < PS3AV_HDR_SIZE);
+	BUG_ON(usr_buf_size < send_len);
+	BUG_ON(usr_buf_size > PS3AV_BUF_SIZE);
+
+	/* create header */
+	ps3av_set_hdr(cid, send_len, buf);
+
+	/* send packet via vuart */
+	res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len,
+				 usr_buf_size);
+	if (res < 0) {
+		printk(KERN_ERR
+		       "%s: ps3av_send_cmd_pkt() failed (result=%d)\n",
+		       __FUNCTION__, res);
+		goto err;
+	}
+
+	/* process reply packet */
+	res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr,
+					 usr_buf_size);
+	if (res < 0) {
+		printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n",
+		       __FUNCTION__, res);
+		goto err;
+	}
+
+	up(&ps3av.sem);
+	return 0;
+
+      err:
+	up(&ps3av.sem);
+	printk(KERN_ERR "%s: failed cid:%x res:%d\n", __FUNCTION__, cid, res);
+	return res;
+}
+
+static int ps3av_set_av_video_mute(u32 mute)
+{
+	int i, num_of_av_port, res;
+
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+			 ps3av.av_hw_conf.num_of_avmulti;
+	/* video mute on */
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int ps3av_set_video_disable_sig(void)
+{
+	int i, num_of_hdmi_port, num_of_av_port, res;
+
+	num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi;
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+			 ps3av.av_hw_conf.num_of_avmulti;
+
+	/* tv mute */
+	for (i = 0; i < num_of_hdmi_port; i++) {
+		res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+					   PS3AV_CMD_MUTE_ON);
+		if (res < 0)
+			return -1;
+	}
+	msleep(100);
+
+	/* video mute on */
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]);
+		if (res < 0)
+			return -1;
+		if (i < num_of_hdmi_port) {
+			res = ps3av_cmd_av_tv_mute(ps3av.av_port[i],
+						   PS3AV_CMD_MUTE_OFF);
+			if (res < 0)
+				return -1;
+		}
+	}
+	msleep(300);
+
+	return 0;
+}
+
+static int ps3av_set_audio_mute(u32 mute)
+{
+	int i, num_of_av_port, num_of_opt_port, res;
+
+	num_of_av_port = ps3av.av_hw_conf.num_of_hdmi +
+			 ps3av.av_hw_conf.num_of_avmulti;
+	num_of_opt_port = ps3av.av_hw_conf.num_of_spdif;
+
+	for (i = 0; i < num_of_av_port; i++) {
+		res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+	for (i = 0; i < num_of_opt_port; i++) {
+		res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute);
+		if (res < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source)
+{
+	struct ps3av_pkt_avb_param avb_param;
+	int i, num_of_audio, vid, res;
+	struct ps3av_pkt_audio_mode audio_mode;
+	u32 len = 0;
+
+	num_of_audio = ps3av.av_hw_conf.num_of_hdmi +
+		       ps3av.av_hw_conf.num_of_avmulti +
+		       ps3av.av_hw_conf.num_of_spdif;
+
+	avb_param.num_of_video_pkt = 0;
+	avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO;	/* always 0 */
+	avb_param.num_of_av_video_pkt = 0;
+	avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi;
+
+	vid = video_mode_table[ps3av.ps3av_mode].vid;
+
+	/* audio mute */
+	ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON);
+
+	/* audio inactive */
+	res = ps3av_cmd_audio_active(0, ps3av.audio_port);
+	if (res < 0)
+		dev_dbg(&ps3av_dev.core,
+			"ps3av_cmd_audio_active OFF failed\n");
+
+	/* audio_pkt */
+	for (i = 0; i < num_of_audio; i++) {
+		ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs,
+					 word_bits, format, source);
+		if (i < ps3av.av_hw_conf.num_of_hdmi) {
+			/* hdmi only */
+			len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len],
+							    ps3av.av_port[i],
+							    &audio_mode, vid);
+		}
+		/* audio_mode pkt should be sent separately */
+		res = ps3av_cmd_audio_mode(&audio_mode);
+		if (res < 0)
+			dev_dbg(&ps3av_dev.core,
+				"ps3av_cmd_audio_mode failed, port:%x\n", i);
+	}
+
+	/* send command using avb pkt */
+	len += offsetof(struct ps3av_pkt_avb_param, buf);
+	res = ps3av_cmd_avb_param(&avb_param, len);
+	if (res < 0)
+		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+
+	/* audio mute */
+	ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF);
+
+	/* audio active */
+	res = ps3av_cmd_audio_active(1, ps3av.audio_port);
+	if (res < 0)
+		dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n");
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_set_audio_mode);
+
+static int ps3av_set_videomode(void)
+{
+	/* av video mute */
+	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON);
+
+	/* wake up ps3avd to do the actual video mode setting */
+	up(&ps3av.ping);
+
+	return 0;
+}
+
+static void ps3av_set_videomode_cont(u32 id, u32 old_id)
+{
+	struct ps3av_pkt_avb_param avb_param;
+	int i;
+	u32 len = 0, av_video_cs;
+	const struct avset_video_mode *video_mode;
+	int res;
+
+	video_mode = &video_mode_table[id & PS3AV_MODE_MASK];
+
+	avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO;	/* num of head */
+	avb_param.num_of_audio_pkt = 0;
+	avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi +
+					ps3av.av_hw_conf.num_of_avmulti;
+	avb_param.num_of_av_audio_pkt = 0;
+
+	/* video signal off */
+	ps3av_set_video_disable_sig();
+
+	/* Retail PS3 product doesn't support this */
+	if (id & PS3AV_MODE_HDCP_OFF) {
+		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF);
+		if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+			dev_dbg(&ps3av_dev.core, "Not supported\n");
+		else if (res)
+			dev_dbg(&ps3av_dev.core,
+				"ps3av_cmd_av_hdmi_mode failed\n");
+	} else if (old_id & PS3AV_MODE_HDCP_OFF) {
+		res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL);
+		if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+			dev_dbg(&ps3av_dev.core,
+				"ps3av_cmd_av_hdmi_mode failed\n");
+	}
+
+	/* video_pkt */
+	for (i = 0; i < avb_param.num_of_video_pkt; i++)
+		len += ps3av_cmd_set_video_mode(&avb_param.buf[len],
+						ps3av.head[i], video_mode->vid,
+						video_mode->fmt, id);
+	/* av_video_pkt */
+	for (i = 0; i < avb_param.num_of_av_video_pkt; i++) {
+		if (id & PS3AV_MODE_DVI || id & PS3AV_MODE_RGB)
+			av_video_cs = RGB8;
+		else
+			av_video_cs = video_mode->cs;
+#ifndef PS3AV_HDMI_YUV
+		if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 ||
+		    ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1)
+			av_video_cs = RGB8;	/* use RGB for HDMI */
+#endif
+		len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len],
+						 ps3av.av_port[i],
+						 video_mode->vid, av_video_cs,
+						 video_mode->aspect, id);
+	}
+	/* send command using avb pkt */
+	len += offsetof(struct ps3av_pkt_avb_param, buf);
+	res = ps3av_cmd_avb_param(&avb_param, len);
+	if (res == PS3AV_STATUS_NO_SYNC_HEAD)
+		printk(KERN_WARNING
+		       "%s: Command failed. Please try your request again. \n",
+		       __FUNCTION__);
+	else if (res)
+		dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n");
+
+	msleep(1500);
+	/* av video mute */
+	ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF);
+}
+
+static int ps3avd(void *p)
+{
+	struct ps3av *info = p;
+
+	daemonize("ps3avd");
+	while (1) {
+		down(&info->ping);
+		ps3av_set_videomode_cont(info->ps3av_mode,
+					 info->ps3av_mode_old);
+		up(&info->pong);
+	}
+	return 0;
+}
+
+static int ps3av_vid2table_id(int vid)
+{
+	int i;
+
+	for (i = 1; i < ARRAY_SIZE(video_mode_table); i++)
+		if (video_mode_table[i].vid == vid)
+			return i;
+	return -1;
+}
+
+static int ps3av_resbit2vid(u32 res_50, u32 res_60)
+{
+	int vid = -1;
+
+	if (res_50 > res_60) {	/* if res_50 == res_60, res_60 will be used */
+		if (res_50 & PS3AV_RESBIT_1920x1080P)
+			vid = PS3AV_CMD_VIDEO_VID_1080P_50HZ;
+		else if (res_50 & PS3AV_RESBIT_1920x1080I)
+			vid = PS3AV_CMD_VIDEO_VID_1080I_50HZ;
+		else if (res_50 & PS3AV_RESBIT_1280x720P)
+			vid = PS3AV_CMD_VIDEO_VID_720P_50HZ;
+		else if (res_50 & PS3AV_RESBIT_720x576P)
+			vid = PS3AV_CMD_VIDEO_VID_576P;
+		else
+			vid = -1;
+	} else {
+		if (res_60 & PS3AV_RESBIT_1920x1080P)
+			vid = PS3AV_CMD_VIDEO_VID_1080P_60HZ;
+		else if (res_60 & PS3AV_RESBIT_1920x1080I)
+			vid = PS3AV_CMD_VIDEO_VID_1080I_60HZ;
+		else if (res_60 & PS3AV_RESBIT_1280x720P)
+			vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+		else if (res_60 & PS3AV_RESBIT_720x480P)
+			vid = PS3AV_CMD_VIDEO_VID_480P;
+		else
+			vid = -1;
+	}
+	return vid;
+}
+
+static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info)
+{
+	u32 res_50, res_60;
+	int vid = -1;
+
+	if (info->monitor_type != PS3AV_MONITOR_TYPE_HDMI)
+		return -1;
+
+	/* check native resolution */
+	res_50 = info->res_50.native & PS3AV_RES_MASK_50;
+	res_60 = info->res_60.native & PS3AV_RES_MASK_60;
+	if (res_50 || res_60) {
+		vid = ps3av_resbit2vid(res_50, res_60);
+		return vid;
+	}
+
+	/* check resolution */
+	res_50 = info->res_50.res_bits & PS3AV_RES_MASK_50;
+	res_60 = info->res_60.res_bits & PS3AV_RES_MASK_60;
+	if (res_50 || res_60) {
+		vid = ps3av_resbit2vid(res_50, res_60);
+		return vid;
+	}
+
+	if (ps3av.region & PS3AV_REGION_60)
+		vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+	else
+		vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+	return vid;
+}
+
+static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf,
+				int boot)
+{
+	int i, res, vid = -1, dvi = 0, rgb = 0;
+	struct ps3av_pkt_av_get_monitor_info monitor_info;
+	struct ps3av_info_monitor *info;
+
+	/* get vid for hdmi */
+	for (i = 0; i < av_hw_conf->num_of_hdmi; i++) {
+		res = ps3av_cmd_video_get_monitor_info(&monitor_info,
+						       PS3AV_CMD_AVPORT_HDMI_0 +
+						       i);
+		if (res < 0)
+			return -1;
+
+		ps3av_cmd_av_monitor_info_dump(&monitor_info);
+		info = &monitor_info.info;
+		/* check DVI */
+		if (info->monitor_type == PS3AV_MONITOR_TYPE_DVI) {
+			dvi = PS3AV_MODE_DVI;
+			break;
+		}
+		/* check HDMI */
+		vid = ps3av_hdmi_get_vid(info);
+		if (vid != -1) {
+			/* got valid vid */
+			break;
+		}
+	}
+
+	if (dvi) {
+		/* DVI mode */
+		vid = PS3AV_DEFAULT_DVI_VID;
+	} else if (vid == -1) {
+		/* no HDMI interface or HDMI is off */
+		if (ps3av.region & PS3AV_REGION_60)
+			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60;
+		else
+			vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50;
+		if (ps3av.region & PS3AV_REGION_RGB)
+			rgb = PS3AV_MODE_RGB;
+	} else if (boot) {
+		/* HDMI: using DEFAULT HDMI_VID while booting up */
+		info = &monitor_info.info;
+		if (ps3av.region & PS3AV_REGION_60) {
+			if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			else {
+				/* default */
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			}
+		} else {
+			if (info->res_50.res_bits & PS3AV_RESBIT_720x576P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			else if (info->res_60.res_bits & PS3AV_RESBIT_720x480P)
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_60;
+			else {
+				/* default */
+				vid = PS3AV_DEFAULT_HDMI_VID_REG_50;
+			}
+		}
+	}
+
+	return (ps3av_vid2table_id(vid) | dvi | rgb);
+}
+
+static int ps3av_get_hw_conf(struct ps3av *ps3av)
+{
+	int i, j, k, res;
+
+	/* get av_hw_conf */
+	res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf);
+	if (res < 0)
+		return -1;
+
+	ps3av_cmd_av_hw_conf_dump(&ps3av->av_hw_conf);
+
+	for (i = 0; i < PS3AV_HEAD_MAX; i++)
+		ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i;
+	for (i = 0; i < PS3AV_OPT_PORT_MAX; i++)
+		ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i;
+	for (i = 0; i < ps3av->av_hw_conf.num_of_hdmi; i++)
+		ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i;
+	for (j = 0; j < ps3av->av_hw_conf.num_of_avmulti; j++)
+		ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j;
+	for (k = 0; k < ps3av->av_hw_conf.num_of_spdif; k++)
+		ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k;
+
+	/* set all audio port */
+	ps3av->audio_port = PS3AV_CMD_AUDIO_PORT_HDMI_0
+	    | PS3AV_CMD_AUDIO_PORT_HDMI_1
+	    | PS3AV_CMD_AUDIO_PORT_AVMULTI_0
+	    | PS3AV_CMD_AUDIO_PORT_SPDIF_0 | PS3AV_CMD_AUDIO_PORT_SPDIF_1;
+
+	return 0;
+}
+
+/* set mode using id */
+int ps3av_set_video_mode(u32 id, int boot)
+{
+	int size;
+	u32 option;
+
+	size = ARRAY_SIZE(video_mode_table);
+	if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) {
+		dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __FUNCTION__,
+			id);
+		return -EINVAL;
+	}
+
+	/* auto mode */
+	option = id & ~PS3AV_MODE_MASK;
+	if ((id & PS3AV_MODE_MASK) == 0) {
+		id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot);
+		if (id < 1) {
+			printk(KERN_ERR "%s: invalid id :%d\n", __FUNCTION__,
+			       id);
+			return -EINVAL;
+		}
+		id |= option;
+	}
+
+	/* set videomode */
+	down(&ps3av.pong);
+	ps3av.ps3av_mode_old = ps3av.ps3av_mode;
+	ps3av.ps3av_mode = id;
+	if (ps3av_set_videomode())
+		ps3av.ps3av_mode = ps3av.ps3av_mode_old;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_set_video_mode);
+
+int ps3av_set_mode(u32 id, int boot)
+{
+	int res;
+
+	res = ps3av_set_video_mode(id, boot);
+	if (res)
+		return res;
+
+	res = ps3av_set_audio_mode(PS3AV_CMD_AUDIO_NUM_OF_CH_2,
+				   PS3AV_CMD_AUDIO_FS_48K,
+				   PS3AV_CMD_AUDIO_WORD_BITS_16,
+				   PS3AV_CMD_AUDIO_FORMAT_PCM,
+				   PS3AV_CMD_AUDIO_SOURCE_SERIAL);
+	if (res)
+		return res;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_set_mode);
+
+int ps3av_get_mode(void)
+{
+	return ps3av.ps3av_mode;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_get_mode);
+
+int ps3av_get_scanmode(int id)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -EINVAL;
+	}
+	return video_mode_table[id].interlace;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_get_scanmode);
+
+int ps3av_get_refresh_rate(int id)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -EINVAL;
+	}
+	return video_mode_table[id].freq;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_get_refresh_rate);
+
+/* get resolution by video_mode */
+int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
+{
+	int size;
+
+	id = id & PS3AV_MODE_MASK;
+	size = ARRAY_SIZE(video_mode_table);
+	if (id > size - 1 || id < 0) {
+		printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id);
+		return -EINVAL;
+	}
+	*xres = video_mode_table[id].x;
+	*yres = video_mode_table[id].y;
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_video_mode2res);
+
+/* mute */
+int ps3av_video_mute(int mute)
+{
+	return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON
+					    : PS3AV_CMD_MUTE_OFF);
+}
+
+EXPORT_SYMBOL_GPL(ps3av_video_mute);
+
+int ps3av_audio_mute(int mute)
+{
+	return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
+					 : PS3AV_CMD_MUTE_OFF);
+}
+
+EXPORT_SYMBOL_GPL(ps3av_audio_mute);
+
+int ps3av_dev_open(void)
+{
+	int status = 0;
+
+	mutex_lock(&ps3av.mutex);
+	if (!ps3av.open_count++) {
+		status = lv1_gpu_open(0);
+		if (status) {
+			printk(KERN_ERR "%s: lv1_gpu_open failed %d\n",
+			       __FUNCTION__, status);
+			ps3av.open_count--;
+		}
+	}
+	mutex_unlock(&ps3av.mutex);
+
+	return status;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_dev_open);
+
+int ps3av_dev_close(void)
+{
+	int status = 0;
+
+	mutex_lock(&ps3av.mutex);
+	if (ps3av.open_count <= 0) {
+		printk(KERN_ERR "%s: GPU already closed\n", __FUNCTION__);
+		status = -1;
+	} else if (!--ps3av.open_count) {
+		status = lv1_gpu_close();
+		if (status)
+			printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n",
+			       __FUNCTION__, status);
+	}
+	mutex_unlock(&ps3av.mutex);
+
+	return status;
+}
+
+EXPORT_SYMBOL_GPL(ps3av_dev_close);
+
+static int ps3av_probe(struct ps3_vuart_port_device *dev)
+{
+	int res;
+	u32 id;
+
+	dev_dbg(&ps3av_dev.core, "init ...\n");
+	dev_dbg(&ps3av_dev.core, "  timeout=%d\n", timeout);
+
+	memset(&ps3av, 0, sizeof(ps3av));
+
+	init_MUTEX(&ps3av.sem);
+	init_MUTEX_LOCKED(&ps3av.ping);
+	init_MUTEX(&ps3av.pong);
+	mutex_init(&ps3av.mutex);
+	ps3av.ps3av_mode = 0;
+	ps3av.dev = dev;
+	kernel_thread(ps3avd, &ps3av, CLONE_KERNEL);
+
+	ps3av.available = 1;
+	switch (ps3_os_area_get_av_multi_out()) {
+	case PS3_PARAM_AV_MULTI_OUT_NTSC:
+		ps3av.region = PS3AV_REGION_60;
+		break;
+	case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR:
+	case PS3_PARAM_AV_MULTI_OUT_SECAM:
+		ps3av.region = PS3AV_REGION_50;
+		break;
+	case PS3_PARAM_AV_MULTI_OUT_PAL_RGB:
+		ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB;
+		break;
+	default:
+		ps3av.region = PS3AV_REGION_60;
+		break;
+	}
+
+	/* init avsetting modules */
+	res = ps3av_cmd_init();
+	if (res < 0)
+		printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __FUNCTION__,
+		       res);
+
+	ps3av_get_hw_conf(&ps3av);
+	id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1);
+	mutex_lock(&ps3av.mutex);
+	ps3av.ps3av_mode = id;
+	mutex_unlock(&ps3av.mutex);
+
+	dev_dbg(&ps3av_dev.core, "init...done\n");
+
+	return 0;
+}
+
+static int ps3av_remove(struct ps3_vuart_port_device *dev)
+{
+	if (ps3av.available) {
+		ps3av_cmd_fin();
+		ps3av.available = 0;
+	}
+
+	return 0;
+}
+
+static void ps3av_shutdown(struct ps3_vuart_port_device *dev)
+{
+	ps3av_remove(dev);
+}
+
+static struct ps3_vuart_port_driver ps3av_driver = {
+	.match_id = PS3_MATCH_ID_AV_SETTINGS,
+	.core = {
+		.name = "ps3_av",
+	},
+	.probe = ps3av_probe,
+	.remove = ps3av_remove,
+	.shutdown = ps3av_shutdown,
+};
+
+static int ps3av_module_init(void)
+{
+	int error = ps3_vuart_port_driver_register(&ps3av_driver);
+	if (error) {
+		printk(KERN_ERR
+		       "%s: ps3_vuart_port_driver_register failed %d\n",
+		       __FUNCTION__, error);
+		return error;
+	}
+
+	error = ps3_vuart_port_device_register(&ps3av_dev);
+	if (error)
+		printk(KERN_ERR
+		       "%s: ps3_vuart_port_device_register failed %d\n",
+		       __FUNCTION__, error);
+
+	return error;
+}
+
+static void __exit ps3av_module_exit(void)
+{
+	device_unregister(&ps3av_dev.core);
+	ps3_vuart_port_driver_unregister(&ps3av_driver);
+}
+
+subsys_initcall(ps3av_module_init);
+module_exit(ps3av_module_exit);
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c
new file mode 100644
index 0000000..21c97c8
--- /dev/null
+++ b/drivers/ps3/ps3av_cmd.c
@@ -0,0 +1,1020 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * AV backend support for PS3
+ *
+ * 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 of the License.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/ps3av.h>
+#include <asm/ps3fb.h>
+#include <asm/ps3.h>
+
+#include "vuart.h"
+
+static const struct video_fmt {
+	u32 format;
+	u32 order;
+} ps3av_video_fmt_table[] = {
+	{ PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_RGB },
+	{ PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_BGR },
+};
+
+static const struct {
+	int cs;
+	u32 av;
+	u32 bl;
+} ps3av_cs_video2av_table[] = {
+	{
+		.cs = PS3AV_CMD_VIDEO_CS_RGB_8,
+		.av = PS3AV_CMD_AV_CS_RGB_8,
+		.bl = PS3AV_CMD_AV_CS_8
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_RGB_10,
+		.av = PS3AV_CMD_AV_CS_RGB_8,
+		.bl = PS3AV_CMD_AV_CS_8
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_RGB_12,
+		.av = PS3AV_CMD_AV_CS_RGB_8,
+		.bl = PS3AV_CMD_AV_CS_8
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV444_8,
+		.av = PS3AV_CMD_AV_CS_YUV444_8,
+		.bl = PS3AV_CMD_AV_CS_8
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV444_10,
+		.av = PS3AV_CMD_AV_CS_YUV444_8,
+		.bl = PS3AV_CMD_AV_CS_10
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV444_12,
+		.av = PS3AV_CMD_AV_CS_YUV444_8,
+		.bl = PS3AV_CMD_AV_CS_10
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV422_8,
+		.av = PS3AV_CMD_AV_CS_YUV422_8,
+		.bl = PS3AV_CMD_AV_CS_10
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV422_10,
+		.av = PS3AV_CMD_AV_CS_YUV422_8,
+		.bl = PS3AV_CMD_AV_CS_10
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_YUV422_12,
+		.av = PS3AV_CMD_AV_CS_YUV422_8,
+		.bl = PS3AV_CMD_AV_CS_12
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_XVYCC_8,
+		.av = PS3AV_CMD_AV_CS_XVYCC_8,
+		.bl = PS3AV_CMD_AV_CS_12
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_XVYCC_10,
+		.av = PS3AV_CMD_AV_CS_XVYCC_8,
+		.bl = PS3AV_CMD_AV_CS_12
+	}, {
+		.cs = PS3AV_CMD_VIDEO_CS_XVYCC_12,
+		.av = PS3AV_CMD_AV_CS_XVYCC_8,
+		.bl = PS3AV_CMD_AV_CS_12
+	}
+};
+
+static u32 ps3av_cs_video2av(int cs)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ps3av_cs_video2av_table); i++)
+		if (ps3av_cs_video2av_table[i].cs == cs)
+			return ps3av_cs_video2av_table[i].av;
+
+	return PS3AV_CMD_AV_CS_RGB_8;
+}
+
+static u32 ps3av_cs_video2av_bitlen(int cs)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ps3av_cs_video2av_table); i++)
+		if (ps3av_cs_video2av_table[i].cs == cs)
+			return ps3av_cs_video2av_table[i].bl;
+
+	return PS3AV_CMD_AV_CS_8;
+}
+
+static const struct {
+	int vid;
+	u32 av;
+} ps3av_vid_video2av_table[] = {
+	{ PS3AV_CMD_VIDEO_VID_480I, PS3AV_CMD_AV_VID_480I },
+	{ PS3AV_CMD_VIDEO_VID_480P, PS3AV_CMD_AV_VID_480P },
+	{ PS3AV_CMD_VIDEO_VID_576I, PS3AV_CMD_AV_VID_576I },
+	{ PS3AV_CMD_VIDEO_VID_576P, PS3AV_CMD_AV_VID_576P },
+	{ PS3AV_CMD_VIDEO_VID_1080I_60HZ, PS3AV_CMD_AV_VID_1080I_60HZ },
+	{ PS3AV_CMD_VIDEO_VID_720P_60HZ, PS3AV_CMD_AV_VID_720P_60HZ },
+	{ PS3AV_CMD_VIDEO_VID_1080P_60HZ, PS3AV_CMD_AV_VID_1080P_60HZ },
+	{ PS3AV_CMD_VIDEO_VID_1080I_50HZ, PS3AV_CMD_AV_VID_1080I_50HZ },
+	{ PS3AV_CMD_VIDEO_VID_720P_50HZ, PS3AV_CMD_AV_VID_720P_50HZ },
+	{ PS3AV_CMD_VIDEO_VID_1080P_50HZ, PS3AV_CMD_AV_VID_1080P_50HZ },
+	{ PS3AV_CMD_VIDEO_VID_WXGA, PS3AV_CMD_AV_VID_WXGA },
+	{ PS3AV_CMD_VIDEO_VID_SXGA, PS3AV_CMD_AV_VID_SXGA },
+	{ PS3AV_CMD_VIDEO_VID_WUXGA, PS3AV_CMD_AV_VID_WUXGA }
+};
+
+static u32 ps3av_vid_video2av(int vid)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ps3av_vid_video2av_table); i++)
+		if (ps3av_vid_video2av_table[i].vid == vid)
+			return ps3av_vid_video2av_table[i].av;
+
+	return PS3AV_CMD_AV_VID_480P;
+}
+
+int ps3av_cmd_init(void)
+{
+	int res;
+	struct ps3av_pkt_av_init av_init;
+	struct ps3av_pkt_video_init video_init;
+	struct ps3av_pkt_audio_init audio_init;
+
+	/* video init */
+	memset(&video_init, 0, sizeof(video_init));
+
+	res = ps3av_do_pkt(PS3AV_CID_VIDEO_INIT, sizeof(video_init.send_hdr),
+			   sizeof(video_init), &video_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&video_init);
+	if (res) {
+		printk(KERN_ERR "PS3AV_CID_VIDEO_INIT: failed %x\n", res);
+		return res;
+	}
+
+	/* audio init */
+	memset(&audio_init, 0, sizeof(audio_init));
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_INIT, sizeof(audio_init.send_hdr),
+			   sizeof(audio_init), &audio_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_init);
+	if (res) {
+		printk(KERN_ERR "PS3AV_CID_AUDIO_INIT: failed %x\n", res);
+		return res;
+	}
+
+	/* av init */
+	memset(&av_init, 0, sizeof(av_init));
+	av_init.event_bit = 0;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_INIT, sizeof(av_init), sizeof(av_init),
+			   &av_init.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_init);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_INIT: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_fin(void)
+{
+	int res;
+	struct ps3av_pkt_av_fin av_fin;
+
+	memset(&av_fin, 0, sizeof(av_fin));
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_FIN, sizeof(av_fin.send_hdr),
+			   sizeof(av_fin), &av_fin.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_fin);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_FIN: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_video_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, send_len, res;
+	struct ps3av_pkt_av_video_mute av_video_mute;
+
+	if (num_of_port > PS3AV_MUTE_PORT_MAX)
+		return -EINVAL;
+
+	memset(&av_video_mute, 0, sizeof(av_video_mute));
+	for (i = 0; i < num_of_port; i++) {
+		av_video_mute.mute[i].avport = port[i];
+		av_video_mute.mute[i].mute = mute;
+	}
+
+	send_len = sizeof(av_video_mute.send_hdr) +
+	    sizeof(struct ps3av_av_mute) * num_of_port;
+	res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_MUTE, send_len,
+			   sizeof(av_video_mute), &av_video_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_video_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_VIDEO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_video_disable_sig(u32 port)
+{
+	int res;
+	struct ps3av_pkt_av_video_disable_sig av_video_sig;
+
+	memset(&av_video_sig, 0, sizeof(av_video_sig));
+	av_video_sig.avport = port;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_DISABLE_SIG,
+			   sizeof(av_video_sig), sizeof(av_video_sig),
+			   &av_video_sig.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_video_sig);
+	if (res)
+		printk(KERN_ERR
+		       "PS3AV_CID_AV_VIDEO_DISABLE_SIG: failed %x port:%x\n",
+		       res, port);
+
+	return res;
+}
+
+int ps3av_cmd_av_tv_mute(u32 avport, u32 mute)
+{
+	int res;
+	struct ps3av_pkt_av_tv_mute tv_mute;
+
+	memset(&tv_mute, 0, sizeof(tv_mute));
+	tv_mute.avport = avport;
+	tv_mute.mute = mute;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_TV_MUTE, sizeof(tv_mute),
+			   sizeof(tv_mute), &tv_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&tv_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_TV_MUTE: failed %x port:%x\n",
+		       res, avport);
+
+	return res;
+}
+
+int ps3av_cmd_enable_event(void)
+{
+	int res;
+	struct ps3av_pkt_av_event av_event;
+
+	memset(&av_event, 0, sizeof(av_event));
+	av_event.event_bit = PS3AV_CMD_EVENT_BIT_UNPLUGGED |
+	    PS3AV_CMD_EVENT_BIT_PLUGGED | PS3AV_CMD_EVENT_BIT_HDCP_DONE;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_ENABLE_EVENT, sizeof(av_event),
+			   sizeof(av_event), &av_event.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_event);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_ENABLE_EVENT: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_av_hdmi_mode(u8 mode)
+{
+	int res;
+	struct ps3av_pkt_av_hdmi_mode hdmi_mode;
+
+	memset(&hdmi_mode, 0, sizeof(hdmi_mode));
+	hdmi_mode.mode = mode;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_HDMI_MODE, sizeof(hdmi_mode),
+			   sizeof(hdmi_mode), &hdmi_mode.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&hdmi_mode);
+	if (res && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE)
+		printk(KERN_ERR "PS3AV_CID_AV_HDMI_MODE: failed %x\n", res);
+
+	return res;
+}
+
+u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out,
+			      int aspect, u32 id)
+{
+	struct ps3av_pkt_av_video_cs *av_video_cs;
+
+	av_video_cs = (struct ps3av_pkt_av_video_cs *)p;
+	if (video_vid == -1)
+		video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+	if (cs_out == -1)
+		cs_out = PS3AV_CMD_VIDEO_CS_YUV444_8;
+	if (aspect == -1)
+		aspect = 0;
+
+	memset(av_video_cs, 0, sizeof(*av_video_cs));
+	ps3av_set_hdr(PS3AV_CID_AV_VIDEO_CS, sizeof(*av_video_cs),
+		      &av_video_cs->send_hdr);
+	av_video_cs->avport = avport;
+	/* should be same as video_mode.resolution */
+	av_video_cs->av_vid = ps3av_vid_video2av(video_vid);
+	av_video_cs->av_cs_out = ps3av_cs_video2av(cs_out);
+	/* should be same as video_mode.video_cs_out */
+	av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8);
+	av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out);
+	av_video_cs->aspect = aspect;
+	if (id & PS3AV_MODE_DITHER) {
+		av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON
+		    | PS3AV_CMD_AV_DITHER_8BIT;
+	} else {
+		/* default off */
+		av_video_cs->dither = PS3AV_CMD_AV_DITHER_OFF;
+	}
+
+	return sizeof(*av_video_cs);
+}
+
+u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt,
+			     u32 id)
+{
+	struct ps3av_pkt_video_mode *video_mode;
+	u32 x, y;
+
+	video_mode = (struct ps3av_pkt_video_mode *)p;
+	if (video_vid == -1)
+		video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ;
+	if (video_fmt == -1)
+		video_fmt = PS3AV_CMD_VIDEO_FMT_X8R8G8B8;
+
+	if (ps3av_video_mode2res(id, &x, &y))
+		return 0;
+
+	/* video mode */
+	memset(video_mode, 0, sizeof(*video_mode));
+	ps3av_set_hdr(PS3AV_CID_VIDEO_MODE, sizeof(*video_mode),
+		      &video_mode->send_hdr);
+	video_mode->video_head = head;
+	if (video_vid == PS3AV_CMD_VIDEO_VID_480I
+	    && head == PS3AV_CMD_VIDEO_HEAD_B)
+		video_mode->video_vid = PS3AV_CMD_VIDEO_VID_480I_A;
+	else
+		video_mode->video_vid = video_vid;
+	video_mode->width = (u16) x;
+	video_mode->height = (u16) y;
+	video_mode->pitch = video_mode->width * 4;	/* line_length */
+	video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT;
+	video_mode->video_format = ps3av_video_fmt_table[video_fmt].format;
+	video_mode->video_order = ps3av_video_fmt_table[video_fmt].order;
+
+	pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n",
+		__FUNCTION__, video_vid, video_mode->width, video_mode->height,
+		video_mode->pitch, video_mode->video_out_format,
+		video_mode->video_format, video_mode->video_order);
+	return sizeof(*video_mode);
+}
+
+int ps3av_cmd_video_format_black(u32 head, u32 video_fmt, u32 mute)
+{
+	int res;
+	struct ps3av_pkt_video_format video_format;
+
+	memset(&video_format, 0, sizeof(video_format));
+	video_format.video_head = head;
+	if (mute != PS3AV_CMD_MUTE_OFF)
+		video_format.video_format = PS3AV_CMD_VIDEO_FORMAT_BLACK;
+	else
+		video_format.video_format =
+		    ps3av_video_fmt_table[video_fmt].format;
+	video_format.video_order = ps3av_video_fmt_table[video_fmt].order;
+
+	res = ps3av_do_pkt(PS3AV_CID_VIDEO_FORMAT, sizeof(video_format),
+			   sizeof(video_format), &video_format.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&video_format);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_VIDEO_FORMAT: failed %x\n", res);
+
+	return res;
+}
+
+
+int ps3av_cmd_av_audio_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, res;
+	struct ps3av_pkt_av_audio_mute av_audio_mute;
+
+	if (num_of_port > PS3AV_MUTE_PORT_MAX)
+		return -EINVAL;
+
+	/* audio mute */
+	memset(&av_audio_mute, 0, sizeof(av_audio_mute));
+	for (i = 0; i < num_of_port; i++) {
+		av_audio_mute.mute[i].avport = port[i];
+		av_audio_mute.mute[i].mute = mute;
+	}
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_AUDIO_MUTE,
+			   sizeof(av_audio_mute.send_hdr) +
+			   sizeof(struct ps3av_av_mute) * num_of_port,
+			   sizeof(av_audio_mute), &av_audio_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&av_audio_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+static const struct {
+	u32 fs;
+	u8 mclk;
+} ps3av_cnv_mclk_table[] = {
+	{ PS3AV_CMD_AUDIO_FS_44K, PS3AV_CMD_AV_MCLK_512 },
+	{ PS3AV_CMD_AUDIO_FS_48K, PS3AV_CMD_AV_MCLK_512 },
+	{ PS3AV_CMD_AUDIO_FS_88K, PS3AV_CMD_AV_MCLK_256 },
+	{ PS3AV_CMD_AUDIO_FS_96K, PS3AV_CMD_AV_MCLK_256 },
+	{ PS3AV_CMD_AUDIO_FS_176K, PS3AV_CMD_AV_MCLK_128 },
+	{ PS3AV_CMD_AUDIO_FS_192K, PS3AV_CMD_AV_MCLK_128 }
+};
+
+static u8 ps3av_cnv_mclk(u32 fs)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ps3av_cnv_mclk_table); i++)
+		if (ps3av_cnv_mclk_table[i].fs == fs)
+			return ps3av_cnv_mclk_table[i].mclk;
+
+	printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+	return 0;
+}
+
+#define BASE	PS3AV_CMD_AUDIO_FS_44K
+
+static const u32 ps3av_ns_table[][5] = {
+					/*   D1,    D2,    D3,    D4,    D5 */
+	[PS3AV_CMD_AUDIO_FS_44K-BASE]	{  6272,  6272, 17836, 17836,  8918 },
+	[PS3AV_CMD_AUDIO_FS_48K-BASE]	{  6144,  6144, 11648, 11648,  5824 },
+	[PS3AV_CMD_AUDIO_FS_88K-BASE]	{ 12544, 12544, 35672, 35672, 17836 },
+	[PS3AV_CMD_AUDIO_FS_96K-BASE]	{ 12288, 12288, 23296, 23296, 11648 },
+	[PS3AV_CMD_AUDIO_FS_176K-BASE]	{ 25088, 25088, 71344, 71344, 35672 },
+	[PS3AV_CMD_AUDIO_FS_192K-BASE]	{ 24576, 24576, 46592, 46592, 23296 }
+};
+
+static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid)
+{
+	u32 av_vid, ns_val;
+	u8 *p = ns;
+	int d;
+
+	d = ns_val = 0;
+	av_vid = ps3av_vid_video2av(video_vid);
+	switch (av_vid) {
+	case PS3AV_CMD_AV_VID_480I:
+	case PS3AV_CMD_AV_VID_576I:
+		d = 0;
+		break;
+	case PS3AV_CMD_AV_VID_480P:
+	case PS3AV_CMD_AV_VID_576P:
+		d = 1;
+		break;
+	case PS3AV_CMD_AV_VID_1080I_60HZ:
+	case PS3AV_CMD_AV_VID_1080I_50HZ:
+		d = 2;
+		break;
+	case PS3AV_CMD_AV_VID_720P_60HZ:
+	case PS3AV_CMD_AV_VID_720P_50HZ:
+		d = 3;
+		break;
+	case PS3AV_CMD_AV_VID_1080P_60HZ:
+	case PS3AV_CMD_AV_VID_1080P_50HZ:
+	case PS3AV_CMD_AV_VID_WXGA:
+	case PS3AV_CMD_AV_VID_SXGA:
+	case PS3AV_CMD_AV_VID_WUXGA:
+		d = 4;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, vid:%x\n", __FUNCTION__,
+		       video_vid);
+		break;
+	}
+
+	if (fs < PS3AV_CMD_AUDIO_FS_44K || fs > PS3AV_CMD_AUDIO_FS_192K)
+		printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs);
+	else
+		ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d];
+
+	*p++ = ns_val & 0x000000FF;
+	*p++ = (ns_val & 0x0000FF00) >> 8;
+	*p = (ns_val & 0x00FF0000) >> 16;
+}
+
+#undef BASE
+
+static u8 ps3av_cnv_enable(u32 source, u8 *enable)
+{
+	u8 *p, ret = 0;
+
+	if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) {
+		ret = 0x03;
+	} else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) {
+		p = enable;
+		ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) |
+		      0x01;
+	} else
+		printk(KERN_ERR "%s failed, source:%x\n", __FUNCTION__,
+		       source);
+	return ret;
+}
+
+static u8 ps3av_cnv_fifomap(u8 *map)
+{
+	u8 *p, ret = 0;
+
+	p = map;
+	ret = p[0] + (p[1] << 2) + (p[2] << 4) + (p[3] << 6);
+	return ret;
+}
+
+static u8 ps3av_cnv_inputlen(u32 word_bits)
+{
+	u8 ret = 0;
+
+	switch (word_bits) {
+	case PS3AV_CMD_AUDIO_WORD_BITS_16:
+		ret = PS3AV_CMD_AV_INPUTLEN_16;
+		break;
+	case PS3AV_CMD_AUDIO_WORD_BITS_20:
+		ret = PS3AV_CMD_AV_INPUTLEN_20;
+		break;
+	case PS3AV_CMD_AUDIO_WORD_BITS_24:
+		ret = PS3AV_CMD_AV_INPUTLEN_24;
+		break;
+	default:
+		printk(KERN_ERR "%s failed, word_bits:%x\n", __FUNCTION__,
+		       word_bits);
+		break;
+	}
+	return ret;
+}
+
+static u8 ps3av_cnv_layout(u32 num_of_ch)
+{
+	if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) {
+		printk(KERN_ERR "%s failed, num_of_ch:%x\n", __FUNCTION__,
+		       num_of_ch);
+		return 0;
+	}
+
+	return num_of_ch == PS3AV_CMD_AUDIO_NUM_OF_CH_2 ? 0x0 : 0x1;
+}
+
+static void ps3av_cnv_info(struct ps3av_audio_info_frame *info,
+			   const struct ps3av_pkt_audio_mode *mode)
+{
+	info->pb1.cc = mode->audio_num_of_ch + 1;	/* CH2:0x01 --- CH8:0x07 */
+	info->pb1.ct = 0;
+	info->pb2.sf = 0;
+	info->pb2.ss = 0;
+
+	info->pb3 = 0;		/* check mode->audio_format ?? */
+	info->pb4 = mode->audio_layout;
+	info->pb5.dm = mode->audio_downmix;
+	info->pb5.lsv = mode->audio_downmix_level;
+}
+
+static void ps3av_cnv_chstat(u8 *chstat, u8 *cs_info)
+{
+	memcpy(chstat, cs_info, 5);
+}
+
+u32 ps3av_cmd_set_av_audio_param(void *p, u32 port,
+				 const struct ps3av_pkt_audio_mode *audio_mode,
+				 u32 video_vid)
+{
+	struct ps3av_pkt_av_audio_param *param;
+
+	param = (struct ps3av_pkt_av_audio_param *)p;
+
+	memset(param, 0, sizeof(*param));
+	ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM, sizeof(*param),
+		      &param->send_hdr);
+
+	param->avport = port;
+	param->mclk = ps3av_cnv_mclk(audio_mode->audio_fs) | 0x80;
+	ps3av_cnv_ns(param->ns, audio_mode->audio_fs, video_vid);
+	param->enable = ps3av_cnv_enable(audio_mode->audio_source,
+					 audio_mode->audio_enable);
+	param->swaplr = 0x09;
+	param->fifomap = ps3av_cnv_fifomap(audio_mode->audio_map);
+	param->inputctrl = 0x49;
+	param->inputlen = ps3av_cnv_inputlen(audio_mode->audio_word_bits);
+	param->layout = ps3av_cnv_layout(audio_mode->audio_num_of_ch);
+	ps3av_cnv_info(&param->info, audio_mode);
+	ps3av_cnv_chstat(param->chstat, audio_mode->audio_cs_info);
+
+	return sizeof(*param);
+}
+
+/* default cs val */
+static const u8 ps3av_mode_cs_info[] = {
+	0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
+};
+
+#define CS_44	0x00
+#define CS_48	0x02
+#define CS_88	0x08
+#define CS_96	0x0a
+#define CS_176	0x0c
+#define CS_192	0x0e
+#define CS_MASK	0x0f
+#define CS_BIT	0x40
+
+void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
+			      u32 ch, u32 fs, u32 word_bits, u32 format,
+			      u32 source)
+{
+	int spdif_through, spdif_bitstream;
+	int i;
+
+	if (!(ch | fs | format | word_bits | source)) {
+		ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2;
+		fs = PS3AV_CMD_AUDIO_FS_48K;
+		word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
+		format = PS3AV_CMD_AUDIO_FORMAT_PCM;
+		source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
+	}
+	spdif_through = spdif_bitstream = 0;	/* XXX not supported */
+
+	/* audio mode */
+	memset(audio, 0, sizeof(*audio));
+	ps3av_set_hdr(PS3AV_CID_AUDIO_MODE, sizeof(*audio), &audio->send_hdr);
+
+	audio->avport = (u8) avport;
+	audio->mask = 0x0FFF;	/* XXX set all */
+	audio->audio_num_of_ch = ch;
+	audio->audio_fs = fs;
+	audio->audio_word_bits = word_bits;
+	audio->audio_format = format;
+	audio->audio_source = source;
+
+	switch (ch) {
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
+		audio->audio_enable[3] = 1;
+		/* fall through */
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
+		audio->audio_enable[2] = 1;
+		audio->audio_enable[1] = 1;
+		/* fall through */
+	case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
+	default:
+		audio->audio_enable[0] = 1;
+	}
+
+	/* audio swap L/R */
+	for (i = 0; i < 4; i++)
+		audio->audio_swap[i] = PS3AV_CMD_AUDIO_SWAP_0;	/* no swap */
+
+	/* audio serial input mapping */
+	audio->audio_map[0] = PS3AV_CMD_AUDIO_MAP_OUTPUT_0;
+	audio->audio_map[1] = PS3AV_CMD_AUDIO_MAP_OUTPUT_1;
+	audio->audio_map[2] = PS3AV_CMD_AUDIO_MAP_OUTPUT_2;
+	audio->audio_map[3] = PS3AV_CMD_AUDIO_MAP_OUTPUT_3;
+
+	/* audio speaker layout */
+	if (avport == PS3AV_CMD_AVPORT_HDMI_0 ||
+	    avport == PS3AV_CMD_AVPORT_HDMI_1) {
+		switch (ch) {
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_8:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_8CH;
+			break;
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_6:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_6CH;
+			break;
+		case PS3AV_CMD_AUDIO_NUM_OF_CH_2:
+		default:
+			audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
+			break;
+		}
+	} else {
+		audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH;
+	}
+
+	/* audio downmix permission */
+	audio->audio_downmix = PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED;
+	/* audio downmix level shift (0:0dB to 15:15dB) */
+	audio->audio_downmix_level = 0;	/* 0dB */
+
+	/* set ch status */
+	for (i = 0; i < 8; i++)
+		audio->audio_cs_info[i] = ps3av_mode_cs_info[i];
+
+	switch (fs) {
+	case PS3AV_CMD_AUDIO_FS_44K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_44;
+		break;
+	case PS3AV_CMD_AUDIO_FS_88K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_88;
+		break;
+	case PS3AV_CMD_AUDIO_FS_96K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_96;
+		break;
+	case PS3AV_CMD_AUDIO_FS_176K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_176;
+		break;
+	case PS3AV_CMD_AUDIO_FS_192K:
+		audio->audio_cs_info[3] &= ~CS_MASK;
+		audio->audio_cs_info[3] |= CS_192;
+		break;
+	default:
+		break;
+	}
+
+	/* pass through setting */
+	if (spdif_through &&
+	    (avport == PS3AV_CMD_AVPORT_SPDIF_0 ||
+	     avport == PS3AV_CMD_AVPORT_SPDIF_1)) {
+		audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
+		audio->audio_source = PS3AV_CMD_AUDIO_SOURCE_SPDIF;
+		if (spdif_bitstream) {
+			audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
+			audio->audio_cs_info[0] |= CS_BIT;
+		}
+	}
+}
+
+int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *audio_mode)
+{
+	int res;
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MODE, sizeof(*audio_mode),
+			   sizeof(*audio_mode), &audio_mode->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(audio_mode);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_MODE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_audio_mute(int num_of_port, u32 *port, u32 mute)
+{
+	int i, res;
+	struct ps3av_pkt_audio_mute audio_mute;
+
+	if (num_of_port > PS3AV_OPT_PORT_MAX)
+		return -EINVAL;
+
+	/* audio mute */
+	memset(&audio_mute, 0, sizeof(audio_mute));
+	for (i = 0; i < num_of_port; i++) {
+		audio_mute.mute[i].avport = port[i];
+		audio_mute.mute[i].mute = mute;
+	}
+
+	res = ps3av_do_pkt(PS3AV_CID_AUDIO_MUTE,
+			   sizeof(audio_mute.send_hdr) +
+			   sizeof(struct ps3av_audio_mute) * num_of_port,
+			   sizeof(audio_mute), &audio_mute.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_mute);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_MUTE: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_audio_active(int active, u32 port)
+{
+	int res;
+	struct ps3av_pkt_audio_active audio_active;
+	u32 cid;
+
+	/* audio active */
+	memset(&audio_active, 0, sizeof(audio_active));
+	audio_active.audio_port = port;
+	cid = active ? PS3AV_CID_AUDIO_ACTIVE : PS3AV_CID_AUDIO_INACTIVE;
+
+	res = ps3av_do_pkt(cid, sizeof(audio_active), sizeof(audio_active),
+			   &audio_active.send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(&audio_active);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid,
+		       res);
+
+	return res;
+}
+
+int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
+{
+	int res;
+
+	ps3fb_flip_ctl(0);	/* flip off */
+
+	/* avb packet */
+	res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
+			   &avb->send_hdr);
+	if (res < 0)
+		goto out;
+
+	res = get_status(avb);
+	if (res)
+		pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __FUNCTION__,
+			 res);
+
+      out:
+	ps3fb_flip_ctl(1);	/* flip on */
+	return res;
+}
+
+int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *hw_conf)
+{
+	int res;
+
+	memset(hw_conf, 0, sizeof(*hw_conf));
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF, sizeof(hw_conf->send_hdr),
+			   sizeof(*hw_conf), &hw_conf->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(hw_conf);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res);
+
+	return res;
+}
+
+int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info,
+				     u32 avport)
+{
+	int res;
+
+	memset(info, 0, sizeof(*info));
+	info->avport = avport;
+
+	res = ps3av_do_pkt(PS3AV_CID_AV_GET_MONITOR_INFO,
+			   sizeof(info->send_hdr) + sizeof(info->avport) +
+			   sizeof(info->reserved),
+			   sizeof(*info), &info->send_hdr);
+	if (res < 0)
+		return res;
+
+	res = get_status(info);
+	if (res)
+		printk(KERN_ERR "PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n",
+		       res);
+
+	return res;
+}
+
+#ifdef PS3AV_DEBUG
+void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf)
+{
+	printk("av_h_conf:num of hdmi:%d\n", hw_conf->num_of_hdmi);
+	printk("av_h_conf:num of avmulti:%d\n", hw_conf->num_of_avmulti);
+	printk("av_h_conf:num of spdif:%d\n", hw_conf->num_of_spdif);
+}
+
+void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info)
+{
+	const struct ps3av_info_monitor *info = &monitor_info->info;
+	const struct ps3av_info_audio *audio = info->audio;
+	int i;
+
+	printk("Monitor Info: size%d\n", monitor_info->send_hdr.size);
+
+	printk("avport:%02x\n", info->avport);
+	printk("monitor_id:");
+	for (i = 0; i < 10; i++)
+		printk("%02x ", info->monitor_id[i]);
+	printk("\nmonitor_type:%02x\n", info->monitor_type);
+	printk("monitor_name:");
+	for (i = 0; i < 16; i++)
+		printk("%c", info->monitor_name[i]);
+
+	/* resolution */
+	printk("\nresolution_60: bits:%08x native:%08x\n",
+	       info->res_60.res_bits, info->res_60.native);
+	printk("resolution_50: bits:%08x native:%08x\n",
+	       info->res_50.res_bits, info->res_50.native);
+	printk("resolution_other: bits:%08x native:%08x\n",
+	       info->res_other.res_bits, info->res_other.native);
+	printk("resolution_vesa: bits:%08x native:%08x\n",
+	       info->res_vesa.res_bits, info->res_vesa.native);
+
+	/* color space */
+	printk("color space    rgb:%02x\n", info->cs.rgb);
+	printk("color space yuv444:%02x\n", info->cs.yuv444);
+	printk("color space yuv422:%02x\n", info->cs.yuv422);
+
+	/* color info */
+	printk("color info   red:X %04x Y %04x\n",
+	       info->color.red_x, info->color.red_y);
+	printk("color info green:X %04x Y %04x\n",
+	       info->color.green_x, info->color.green_y);
+	printk("color info  blue:X %04x Y %04x\n",
+	       info->color.blue_x, info->color.blue_y);
+	printk("color info white:X %04x Y %04x\n",
+	       info->color.white_x, info->color.white_y);
+	printk("color info gamma: %08x\n", info->color.gamma);
+
+	/* other info */
+	printk("supported_AI:%02x\n", info->supported_ai);
+	printk("speaker_info:%02x\n", info->speaker_info);
+	printk("num of audio:%02x\n", info->num_of_audio_block);
+
+	/* audio block */
+	for (i = 0; i < info->num_of_audio_block; i++) {
+		printk("audio[%d] type:%02x max_ch:%02x fs:%02x sbit:%02x\n",
+		       i, audio->type, audio->max_num_of_ch, audio->fs,
+		       audio->sbit);
+		audio++;
+	}
+}
+#endif /* PS3AV_DEBUG */
+
+#define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \
+		| PS3AV_CMD_AV_LAYOUT_44 \
+		| PS3AV_CMD_AV_LAYOUT_48)
+
+#define PS3AV_AV_LAYOUT_1 (PS3AV_AV_LAYOUT_0 \
+		| PS3AV_CMD_AV_LAYOUT_88 \
+		| PS3AV_CMD_AV_LAYOUT_96 \
+		| PS3AV_CMD_AV_LAYOUT_176 \
+		| PS3AV_CMD_AV_LAYOUT_192)
+
+/************************* vuart ***************************/
+
+#define POLLING_INTERVAL  25	/* in msec */
+
+int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf,
+		      unsigned long size)
+{
+	int error = ps3_vuart_write(dev, buf, size);
+	return error ? error : size;
+}
+
+int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
+		     unsigned long size, int timeout)
+{
+	int error;
+	int loopcnt = 0;
+
+	timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL;
+	while (loopcnt++ <= timeout) {
+		error = ps3_vuart_read(dev, buf, size);
+		if (!error)
+			return size;
+		if (error != -EAGAIN) {
+			printk(KERN_ERR "%s: ps3_vuart_read failed %d\n",
+			       __FUNCTION__, error);
+			return error;
+		}
+		msleep(POLLING_INTERVAL);
+	}
+	return -EWOULDBLOCK;
+}
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index a72da8f..ef8fd4c 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -867,6 +867,22 @@
 	return 0;
 }
 
+static void ps3_vuart_shutdown(struct device *_dev)
+{
+	struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
+	struct ps3_vuart_port_driver *drv =
+		to_ps3_vuart_port_driver(_dev->driver);
+
+	dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
+		dev->core.bus_id);
+
+	if (drv->shutdown)
+		drv->shutdown(dev);
+	else
+		dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__,
+			__LINE__, dev->core.bus_id);
+}
+
 /**
  * ps3_vuart - The vuart instance.
  *
@@ -878,6 +894,7 @@
 	.match = ps3_vuart_match,
 	.probe = ps3_vuart_probe,
 	.remove = ps3_vuart_remove,
+	.shutdown = ps3_vuart_shutdown,
 };
 
 int __init ps3_vuart_init(void)
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
index 11c421c..2cbf728 100644
--- a/drivers/ps3/vuart.h
+++ b/drivers/ps3/vuart.h
@@ -30,6 +30,7 @@
 	struct device_driver core;
 	int (*probe)(struct ps3_vuart_port_device *);
 	int (*remove)(struct ps3_vuart_port_device *);
+	void (*shutdown)(struct ps3_vuart_port_device *);
 	int (*tx_event)(struct ps3_vuart_port_device *dev);
 	int (*rx_event)(struct ps3_vuart_port_device *dev);
 	int (*disconnect_event)(struct ps3_vuart_port_device *dev);
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 82f2ac8..137330b 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -384,7 +384,7 @@
 	return fasync_helper(fd, file, on, &rtc->async_queue);
 }
 
-static struct file_operations rtc_dev_fops = {
+static const struct file_operations rtc_dev_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= rtc_dev_read,
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 001eb11..e27176c 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -297,7 +297,7 @@
 	.write = ds1553_nvram_write,
 };
 
-static int __init ds1553_rtc_probe(struct platform_device *pdev)
+static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 	struct resource *res;
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 17633bf..d68288b 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -165,7 +165,7 @@
 	.write = ds1742_nvram_write,
 };
 
-static int __init ds1742_rtc_probe(struct platform_device *pdev)
+static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 	struct resource *res;
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index c272afd..1bd624f 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -96,7 +96,7 @@
 	return res;
 }
 
-static struct file_operations rtc_proc_fops = {
+static const struct file_operations rtc_proc_fops = {
 	.open		= rtc_proc_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 2ddd0cf..899ab8c 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -78,6 +78,92 @@
 	.attrs = rtc_attrs,
 };
 
+
+static ssize_t
+rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf)
+{
+	ssize_t retval;
+	unsigned long alarm;
+	struct rtc_wkalrm alm;
+
+	/* Don't show disabled alarms; but the RTC could leave the
+	 * alarm enabled after it's already triggered.  Alarms are
+	 * conceptually one-shot, even though some common hardware
+	 * (PCs) doesn't actually work that way.
+	 *
+	 * REVISIT maybe we should require RTC implementations to
+	 * disable the RTC alarm after it triggers, for uniformity.
+	 */
+	retval = rtc_read_alarm(dev, &alm);
+	if (retval == 0 && alm.enabled) {
+		rtc_tm_to_time(&alm.time, &alarm);
+		retval = sprintf(buf, "%lu\n", alarm);
+	}
+
+	return retval;
+}
+
+static ssize_t
+rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n)
+{
+	ssize_t retval;
+	unsigned long now, alarm;
+	struct rtc_wkalrm alm;
+
+	/* Only request alarms that trigger in the future.  Disable them
+	 * by writing another time, e.g. 0 meaning Jan 1 1970 UTC.
+	 */
+	retval = rtc_read_time(dev, &alm.time);
+	if (retval < 0)
+		return retval;
+	rtc_tm_to_time(&alm.time, &now);
+
+	alarm = simple_strtoul(buf, NULL, 0);
+	if (alarm > now) {
+		/* Avoid accidentally clobbering active alarms; we can't
+		 * entirely prevent that here, without even the minimal
+		 * locking from the /dev/rtcN api.
+		 */
+		retval = rtc_read_alarm(dev, &alm);
+		if (retval < 0)
+			return retval;
+		if (alm.enabled)
+			return -EBUSY;
+
+		alm.enabled = 1;
+	} else {
+		alm.enabled = 0;
+
+		/* Provide a valid future alarm time.  Linux isn't EFI,
+		 * this time won't be ignored when disabling the alarm.
+		 */
+		alarm = now + 300;
+	}
+	rtc_time_to_tm(alarm, &alm.time);
+
+	retval = rtc_set_alarm(dev, &alm);
+	return (retval < 0) ? retval : n;
+}
+static const CLASS_DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR,
+		rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm);
+
+
+/* The reason to trigger an alarm with no process watching it (via sysfs)
+ * is its side effect:  waking from a system state like suspend-to-RAM or
+ * suspend-to-disk.  So: no attribute unless that side effect is possible.
+ * (Userspace may disable that mechanism later.)
+ */
+static inline int rtc_does_wakealarm(struct class_device *class_dev)
+{
+	struct rtc_device *rtc;
+
+	if (!device_can_wakeup(class_dev->dev))
+		return 0;
+	rtc = to_rtc_device(class_dev);
+	return rtc->ops->set_alarm != NULL;
+}
+
+
 static int rtc_sysfs_add_device(struct class_device *class_dev,
 					struct class_interface *class_intf)
 {
@@ -87,8 +173,18 @@
 
 	err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group);
 	if (err)
-		dev_err(class_dev->dev,
-			"failed to create sysfs attributes\n");
+		dev_err(class_dev->dev, "failed to create %s\n",
+				"sysfs attributes");
+	else if (rtc_does_wakealarm(class_dev)) {
+		/* not all RTCs support both alarms and wakeup */
+		err = class_device_create_file(class_dev,
+					&class_device_attr_wakealarm);
+		if (err) {
+			dev_err(class_dev->dev, "failed to create %s\n",
+					"alarm attribute");
+			sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
+		}
+	}
 
 	return err;
 }
@@ -96,6 +192,9 @@
 static void rtc_sysfs_remove_device(struct class_device *class_dev,
 				struct class_interface *class_intf)
 {
+	if (rtc_does_wakealarm(class_dev))
+		class_device_remove_file(class_dev,
+				&class_device_attr_wakealarm);
 	sysfs_remove_group(&class_dev->kobj, &rtc_attr_group);
 }
 
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 6cedc91..4b8a95f 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -650,7 +650,7 @@
 	return mask;
 }
 
-static struct file_operations dasd_eer_fops = {
+static const struct file_operations dasd_eer_fops = {
 	.open		= &dasd_eer_open,
 	.release	= &dasd_eer_close,
 	.read		= &dasd_eer_read,
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 8b7e118..8b3b0f4 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -147,7 +147,7 @@
 	return seq_open(file, &dasd_devices_seq_ops);
 }
 
-static struct file_operations dasd_devices_file_ops = {
+static const struct file_operations dasd_devices_file_ops = {
 	.open		= dasd_devices_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index e1a7462..ef36f213 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -493,7 +493,7 @@
 	return 0;
 }
 
-static struct file_operations fs3270_fops = {
+static const struct file_operations fs3270_fops = {
 	.owner		 = THIS_MODULE,		/* owner */
 	.read		 = fs3270_read,		/* read */
 	.write		 = fs3270_write,	/* write */
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 3a1a958..8df7b13 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -547,7 +547,7 @@
 	return 0;
 }
 
-static struct file_operations mon_fops = {
+static const struct file_operations mon_fops = {
 	.owner   = THIS_MODULE,
 	.open    = &mon_open,
 	.release = &mon_close,
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 9e451ac..268598e 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -255,7 +255,7 @@
 	return rc;
 }
 
-static struct file_operations monwrite_fops = {
+static const struct file_operations monwrite_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = &monwrite_open,
 	.release = &monwrite_close,
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 9faea04..b830a8c 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -39,7 +39,7 @@
 static long tapechar_compat_ioctl(struct file *, unsigned int,
 			  unsigned long);
 
-static struct file_operations tape_fops =
+static const struct file_operations tape_fops =
 {
 	.owner = THIS_MODULE,
 	.read = tapechar_read,
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 56b8761..2e0d297 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -36,7 +36,7 @@
 struct tape_class_device *register_tape_dev(
 	struct device *		device,
 	dev_t			dev,
-	struct file_operations *fops,
+	const struct file_operations *fops,
 	char *			device_name,
 	char *			mode_name)
 {
diff --git a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
index 3d0ca05..a8bd9b4 100644
--- a/drivers/s390/char/tape_class.h
+++ b/drivers/s390/char/tape_class.h
@@ -52,7 +52,7 @@
 struct tape_class_device *register_tape_dev(
 	struct device *		device,
 	dev_t			dev,
-	struct file_operations *fops,
+	const struct file_operations *fops,
 	char *			device_name,
 	char *			node_name
 );
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index 655d375..cea49f0 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -109,7 +109,7 @@
 	return seq_open(file, &tape_proc_seq);
 }
 
-static struct file_operations tape_proc_ops =
+static const struct file_operations tape_proc_ops =
 {
 	.open		= tape_proc_open,
 	.read		= seq_read,
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index a420cd0..fce3dac 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -173,7 +173,7 @@
 	}
 }
 
-static struct file_operations vmcp_fops = {
+static const struct file_operations vmcp_fops = {
 	.owner		= THIS_MODULE,
 	.open		= &vmcp_open,
 	.release	= &vmcp_release,
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 8432a76..b87d3b0 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -88,7 +88,7 @@
 static ssize_t vmlogrdr_read (struct file *filp, char __user *data,
 			      size_t count, loff_t * ppos);
 
-static struct file_operations vmlogrdr_fops = {
+static const struct file_operations vmlogrdr_fops = {
 	.owner   = THIS_MODULE,
 	.open    = vmlogrdr_open,
 	.release = vmlogrdr_release,
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 4b868f7..680b9b5 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -228,7 +228,7 @@
 	return count;
 }
 
-static struct file_operations vmwdt_fops = {
+static const struct file_operations vmwdt_fops = {
 	.open    = &vmwdt_open,
 	.release = &vmwdt_close,
 	.ioctl   = &vmwdt_ioctl,
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index aa65df4..ec04048 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -364,7 +364,7 @@
 	return seq_open(file, &cio_ignore_proc_seq_ops);
 }
 
-static struct file_operations cio_ignore_proc_fops = {
+static const struct file_operations cio_ignore_proc_fops = {
 	.open    = cio_ignore_proc_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 2c78514..9976139 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -807,7 +807,7 @@
 /**
  * Misc device file operations.
  */
-static struct file_operations zcrypt_fops = {
+static const struct file_operations zcrypt_fops = {
 	.owner		= THIS_MODULE,
 	.read		= zcrypt_read,
 	.write		= zcrypt_write,
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index faa768e..81f805c 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -161,7 +161,7 @@
 	return seq_open(file, &qeth_procfile_seq_ops);
 }
 
-static struct file_operations qeth_procfile_fops = {
+static const struct file_operations qeth_procfile_fops = {
 	.owner   = THIS_MODULE,
 	.open    = qeth_procfile_open,
 	.read    = seq_read,
@@ -273,7 +273,7 @@
 	return seq_open(file, &qeth_perf_procfile_seq_ops);
 }
 
-static struct file_operations qeth_perf_procfile_fops = {
+static const struct file_operations qeth_perf_procfile_fops = {
 	.owner   = THIS_MODULE,
 	.open    = qeth_perf_procfile_open,
 	.read    = seq_read,
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 39a8852..1f9554e 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -60,7 +60,7 @@
 	_IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_sense_data)
 
 
-static struct file_operations zfcp_cfdc_fops = {
+static const struct file_operations zfcp_cfdc_fops = {
 	.unlocked_ioctl = zfcp_cfdc_dev_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = zfcp_cfdc_dev_ioctl
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index ac7d125..a39ee80 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -846,7 +846,7 @@
       return errno;
 }
 
-static struct file_operations bpp_fops = {
+static const struct file_operations bpp_fops = {
 	.owner =	THIS_MODULE,
 	.read =		bpp_read,
 	.write =	bpp_write,
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index ad1c7db..0cfd1e4 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -459,7 +459,7 @@
 	return IRQ_HANDLED;
 }
 
-static struct file_operations wd_fops = {
+static const struct file_operations wd_fops = {
 	.owner =	THIS_MODULE,
 	.ioctl =	wd_ioctl,
 	.compat_ioctl =	wd_compat_ioctl,
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index a4909e0..2d14a29 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -166,7 +166,7 @@
 	return error;
 }
 
-static struct file_operations d7s_fops = {
+static const struct file_operations d7s_fops = {
 	.owner =		THIS_MODULE,
 	.unlocked_ioctl =	d7s_ioctl,
 	.compat_ioctl =		d7s_ioctl,
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index fff4660..2cea4f5 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -705,7 +705,7 @@
 	return 0;
 }
 
-static struct file_operations envctrl_fops = {
+static const struct file_operations envctrl_fops = {
 	.owner =		THIS_MODULE,
 	.read =			envctrl_read,
 	.unlocked_ioctl =	envctrl_ioctl,
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index fa2418f..6e99507 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -142,7 +142,7 @@
 	return 0;
 }
 
-static struct file_operations flash_fops = {
+static const struct file_operations flash_fops = {
 	/* no write to the Flash, use mmap
 	 * and play flash dependent tricks.
 	 */
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c
index 14631ac..512857a 100644
--- a/drivers/sbus/char/jsflash.c
+++ b/drivers/sbus/char/jsflash.c
@@ -431,7 +431,7 @@
 	return 0;
 }
 
-static struct file_operations jsf_fops = {
+static const struct file_operations jsf_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	jsf_lseek,
 	.read =		jsf_read,
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 4e2a0e2..e877623 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -704,7 +704,7 @@
 	return 0;
 }
 
-static struct file_operations openprom_fops = {
+static const struct file_operations openprom_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	openprom_ioctl,
diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/sbus/char/riowatchdog.c
index 2a9cc82..a2fc6b8 100644
--- a/drivers/sbus/char/riowatchdog.c
+++ b/drivers/sbus/char/riowatchdog.c
@@ -193,7 +193,7 @@
 	return 0;
 }
 
-static struct file_operations riowd_fops = {
+static const struct file_operations riowd_fops = {
 	.owner =	THIS_MODULE,
 	.ioctl =	riowd_ioctl,
 	.open =		riowd_open,
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
index 9b988ba..94d1858 100644
--- a/drivers/sbus/char/rtc.c
+++ b/drivers/sbus/char/rtc.c
@@ -233,7 +233,7 @@
 	return 0;
 }
 
-static struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	rtc_ioctl,
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index b30372f..4d1a505 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -224,7 +224,7 @@
 	return IRQ_HANDLED;
 }
 
-static struct file_operations uctrl_fops = {
+static const struct file_operations uctrl_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	uctrl_ioctl,
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 386e7de..37a04a0 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -44,7 +44,7 @@
 #include "vfc.h"
 #include <asm/vfc_ioctls.h>
 
-static struct file_operations vfc_fops;
+static const struct file_operations vfc_fops;
 struct vfc_dev **vfc_dev_lst;
 static char vfcstr[]="vfc";
 static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
@@ -633,7 +633,7 @@
 }
 
 
-static struct file_operations vfc_fops = {
+static const struct file_operations vfc_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	vfc_ioctl,
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index b091a0f..eb766c3 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -197,7 +197,7 @@
 };
 
 /* File operations struct for character device */
-static struct file_operations twa_fops = {
+static const struct file_operations twa_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= twa_chrdev_ioctl,
 	.open		= twa_chrdev_open,
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index e1b44d6..bf5d63e 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1040,7 +1040,7 @@
 } /* End tw_chrdev_open() */
 
 /* File operations struct for character device */
-static struct file_operations tw_fops = {
+static const struct file_operations tw_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= tw_chrdev_ioctl,
 	.open		= tw_chrdev_open,
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index a9734e0..0f948c2 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -774,7 +774,7 @@
 };
 
 
-static struct file_operations aac_cfg_fops = {
+static const struct file_operations aac_cfg_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= aac_cfg_ioctl,
 #ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index f6caa43..d02759f 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -129,7 +129,7 @@
 	},
 };
 
-static struct file_operations changer_fops =
+static const struct file_operations changer_fops =
 {
 	.owner        = THIS_MODULE,
 	.open         = ch_open,
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 365db53..cd36e81 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -116,7 +116,7 @@
 static adpt_hba* hba_chain = NULL;
 static int hba_count = 0;
 
-static struct file_operations adpt_fops = {
+static const struct file_operations adpt_fops = {
 	.ioctl		= adpt_ioctl,
 	.open		= adpt_open,
 	.release	= adpt_close
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 4c698a7..a199292 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -687,7 +687,7 @@
 MODULE_LICENSE("GPL");
 
 /* ioctl interface */
-static struct file_operations gdth_fops = {
+static const struct file_operations gdth_fops = {
     .ioctl   = gdth_ioctl,
     .open    = gdth_open,
     .release = gdth_close,
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 77d9d38..808a1b8 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -92,7 +92,7 @@
 /*
  * The File Operations structure for the serial/ioctl interface of the driver
  */
-static struct file_operations megadev_fops = {
+static const struct file_operations megadev_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= megadev_ioctl,
 	.open		= megadev_open,
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index c1ff20c..f33a678 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -67,7 +67,7 @@
 
 static wait_queue_head_t wait_q;
 
-static struct file_operations lsi_fops = {
+static const struct file_operations lsi_fops = {
 	.open	= mraid_mm_open,
 	.ioctl	= mraid_mm_ioctl,
 #ifdef CONFIG_COMPAT
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index b5bdd0d..15e24fc 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -2913,7 +2913,7 @@
 /*
  * File operations structure for management interface
  */
-static struct file_operations megasas_mgmt_fops = {
+static const struct file_operations megasas_mgmt_fops = {
 	.owner = THIS_MODULE,
 	.open = megasas_mgmt_open,
 	.release = megasas_mgmt_release,
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index bd6bbf6..9668b73 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5522,7 +5522,7 @@
 
 #endif
 
-static struct file_operations osst_fops = {
+static const struct file_operations osst_fops = {
 	.owner =        THIS_MODULE,
 	.read =         osst_read,
 	.write =        osst_write,
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 524a5f7..69d6e9b 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -308,7 +308,7 @@
 	return single_open(file, proc_scsi_show, NULL);
 }
 
-static struct file_operations proc_scsi_operations = {
+static const struct file_operations proc_scsi_operations = {
 	.open		= proc_scsi_open,
 	.read		= seq_read,
 	.write		= proc_scsi_write,
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c
index 37bbfbd..f2344ab 100644
--- a/drivers/scsi/scsi_tgt_if.c
+++ b/drivers/scsi/scsi_tgt_if.c
@@ -280,7 +280,7 @@
 	return 0;
 }
 
-static struct file_operations tgt_fops = {
+static const struct file_operations tgt_fops = {
 	.owner		= THIS_MODULE,
 	.open		= tgt_open,
 	.poll		= tgt_poll,
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 16e279b..3d2e023 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3864,7 +3864,7 @@
 
 #endif
 
-static struct file_operations st_fops =
+static const struct file_operations st_fops =
 {
 	.owner =	THIS_MODULE,
 	.read =		st_read,
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 881f886..df45a7a 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -73,35 +73,35 @@
 
 #define ATMEL_ISR_PASS_LIMIT	256
 
-#define UART_PUT_CR(port,v)	writel(v, (port)->membase + ATMEL_US_CR)
-#define UART_GET_MR(port)	readl((port)->membase + ATMEL_US_MR)
-#define UART_PUT_MR(port,v)	writel(v, (port)->membase + ATMEL_US_MR)
-#define UART_PUT_IER(port,v)	writel(v, (port)->membase + ATMEL_US_IER)
-#define UART_PUT_IDR(port,v)	writel(v, (port)->membase + ATMEL_US_IDR)
-#define UART_GET_IMR(port)	readl((port)->membase + ATMEL_US_IMR)
-#define UART_GET_CSR(port)	readl((port)->membase + ATMEL_US_CSR)
-#define UART_GET_CHAR(port)	readl((port)->membase + ATMEL_US_RHR)
-#define UART_PUT_CHAR(port,v)	writel(v, (port)->membase + ATMEL_US_THR)
-#define UART_GET_BRGR(port)	readl((port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_BRGR(port,v)	writel(v, (port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_RTOR(port,v)	writel(v, (port)->membase + ATMEL_US_RTOR)
+#define UART_PUT_CR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_CR)
+#define UART_GET_MR(port)	__raw_readl((port)->membase + ATMEL_US_MR)
+#define UART_PUT_MR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_MR)
+#define UART_PUT_IER(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IER)
+#define UART_PUT_IDR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_IDR)
+#define UART_GET_IMR(port)	__raw_readl((port)->membase + ATMEL_US_IMR)
+#define UART_GET_CSR(port)	__raw_readl((port)->membase + ATMEL_US_CSR)
+#define UART_GET_CHAR(port)	__raw_readl((port)->membase + ATMEL_US_RHR)
+#define UART_PUT_CHAR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_THR)
+#define UART_GET_BRGR(port)	__raw_readl((port)->membase + ATMEL_US_BRGR)
+#define UART_PUT_BRGR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_BRGR)
+#define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
 
-// #define UART_GET_CR(port)	readl((port)->membase + ATMEL_US_CR)		// is write-only
+// #define UART_GET_CR(port)	__raw_readl((port)->membase + ATMEL_US_CR)		// is write-only
 
  /* PDC registers */
-#define UART_PUT_PTCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_PTCR)
-#define UART_GET_PTSR(port)	readl((port)->membase + ATMEL_PDC_PTSR)
+#define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
+#define UART_GET_PTSR(port)	__raw_readl((port)->membase + ATMEL_PDC_PTSR)
 
-#define UART_PUT_RPR(port,v)	writel(v, (port)->membase + ATMEL_PDC_RPR)
-#define UART_GET_RPR(port)	readl((port)->membase + ATMEL_PDC_RPR)
-#define UART_PUT_RCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_RCR)
-#define UART_PUT_RNPR(port,v)	writel(v, (port)->membase + ATMEL_PDC_RNPR)
-#define UART_PUT_RNCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_RNCR)
+#define UART_PUT_RPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
+#define UART_GET_RPR(port)	__raw_readl((port)->membase + ATMEL_PDC_RPR)
+#define UART_PUT_RCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
+#define UART_PUT_RNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
+#define UART_PUT_RNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
 
-#define UART_PUT_TPR(port,v)	writel(v, (port)->membase + ATMEL_PDC_TPR)
-#define UART_PUT_TCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_TCR)
-//#define UART_PUT_TNPR(port,v)	writel(v, (port)->membase + ATMEL_PDC_TNPR)
-//#define UART_PUT_TNCR(port,v)	writel(v, (port)->membase + ATMEL_PDC_TNCR)
+#define UART_PUT_TPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
+#define UART_PUT_TCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
+//#define UART_PUT_TNPR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TNPR)
+//#define UART_PUT_TNCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_TNCR)
 
 static int (*atmel_open_hook)(struct uart_port *);
 static void (*atmel_close_hook)(struct uart_port *);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index d895a1a..9052f4c 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -75,6 +75,13 @@
 	  inexpensive battery powered microcontroller evaluation board.
 	  This same cable can be used to flash new firmware.
 
+config SPI_IMX
+	tristate "Freescale iMX SPI controller"
+	depends on SPI_MASTER && ARCH_IMX && EXPERIMENTAL
+	help
+	  This enables using the Freescale iMX SPI controller in master
+	  mode.
+
 config SPI_MPC83xx
 	tristate "Freescale MPC83xx SPI controller"
 	depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL
@@ -87,6 +94,14 @@
 	  family of PowerPC processors.  The MPC83xx uses a simple set of shift
 	  registers for data (opposed to the CPM based descriptor model).
 
+config SPI_OMAP_UWIRE
+	tristate "OMAP1 MicroWire"
+	depends on SPI_MASTER && ARCH_OMAP1
+	select SPI_BITBANG
+	help
+	  This hooks up to the MicroWire controller on OMAP1 chips.
+
+
 config SPI_PXA2XX
 	tristate "PXA2xx SSP SPI master"
 	depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL
@@ -95,6 +110,12 @@
 	  The driver can be configured to use any SSP port and additional
 	  documentation can be found a Documentation/spi/pxa2xx.
 
+config SPI_S3C24XX
+	tristate "Samsung S3C24XX series SPI"
+	depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
+	help
+	  SPI driver for Samsung S3C24XX series ARM SoCs
+
 config SPI_S3C24XX_GPIO
 	tristate "Samsung S3C24XX series SPI by GPIO"
 	depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL
@@ -107,13 +128,6 @@
 # Add new SPI master controllers in alphabetical order above this line
 #
 
-
-config SPI_S3C24XX
-	tristate "Samsung S3C24XX series SPI"
-	depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL
-	help
-	  SPI driver for Samsung S3C24XX series ARM SoCs
-
 #
 # There are lots of SPI device types, with sensors and memory
 # being probably the most widely used ones.
@@ -121,6 +135,16 @@
 comment "SPI Protocol Masters"
 	depends on SPI_MASTER
 
+config SPI_AT25
+	tristate "SPI EEPROMs from most vendors"
+	depends on SPI_MASTER && SYSFS
+	help
+	  Enable this driver to get read/write support to most SPI EEPROMs,
+	  after you configure the board init code to know about each eeprom
+	  on your target board.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called at25.
 
 #
 # Add new SPI protocol masters in alphabetical order above this line
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8f4cb67..bf271fe 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -13,13 +13,16 @@
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
+obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
+obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
 obj-$(CONFIG_SPI_MPC83xx)		+= spi_mpc83xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx.o
 # 	... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
+obj-$(CONFIG_SPI_AT25)		+= at25.o
 # 	... add above this line ...
 
 # SPI slave controller drivers (upstream link)
diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c
new file mode 100644
index 0000000..48e4f48
--- /dev/null
+++ b/drivers/spi/at25.c
@@ -0,0 +1,381 @@
+/*
+ * at25.c -- support most SPI EEPROMs, such as Atmel AT25 models
+ *
+ * Copyright (C) 2006 David Brownell
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
+
+
+struct at25_data {
+	struct spi_device	*spi;
+	struct mutex		lock;
+	struct spi_eeprom	chip;
+	struct bin_attribute	bin;
+	unsigned		addrlen;
+};
+
+#define	AT25_WREN	0x06		/* latch the write enable */
+#define	AT25_WRDI	0x04		/* reset the write enable */
+#define	AT25_RDSR	0x05		/* read status register */
+#define	AT25_WRSR	0x01		/* write status register */
+#define	AT25_READ	0x03		/* read byte(s) */
+#define	AT25_WRITE	0x02		/* write byte(s)/sector */
+
+#define	AT25_SR_nRDY	0x01		/* nRDY = write-in-progress */
+#define	AT25_SR_WEN	0x02		/* write enable (latched) */
+#define	AT25_SR_BP0	0x04		/* BP for software writeprotect */
+#define	AT25_SR_BP1	0x08
+#define	AT25_SR_WPEN	0x80		/* writeprotect enable */
+
+
+#define EE_MAXADDRLEN	3		/* 24 bit addresses, up to 2 MBytes */
+
+/* Specs often allow 5 msec for a page write, sometimes 20 msec;
+ * it's important to recover from write timeouts.
+ */
+#define	EE_TIMEOUT	25
+
+/*-------------------------------------------------------------------------*/
+
+#define	io_limit	PAGE_SIZE	/* bytes */
+
+static ssize_t
+at25_ee_read(
+	struct at25_data	*at25,
+	char			*buf,
+	unsigned		offset,
+	size_t			count
+)
+{
+	u8			command[EE_MAXADDRLEN + 1];
+	u8			*cp;
+	ssize_t			status;
+	struct spi_transfer	t[2];
+	struct spi_message	m;
+
+	cp = command;
+	*cp++ = AT25_READ;
+
+	/* 8/16/24-bit address is written MSB first */
+	switch (at25->addrlen) {
+	default:	/* case 3 */
+		*cp++ = offset >> 16;
+	case 2:
+		*cp++ = offset >> 8;
+	case 1:
+	case 0:	/* can't happen: for better codegen */
+		*cp++ = offset >> 0;
+	}
+
+	spi_message_init(&m);
+	memset(t, 0, sizeof t);
+
+	t[0].tx_buf = command;
+	t[0].len = at25->addrlen + 1;
+	spi_message_add_tail(&t[0], &m);
+
+	t[1].rx_buf = buf;
+	t[1].len = count;
+	spi_message_add_tail(&t[1], &m);
+
+	mutex_lock(&at25->lock);
+
+	/* Read it all at once.
+	 *
+	 * REVISIT that's potentially a problem with large chips, if
+	 * other devices on the bus need to be accessed regularly or
+	 * this chip is clocked very slowly
+	 */
+	status = spi_sync(at25->spi, &m);
+	dev_dbg(&at25->spi->dev,
+		"read %Zd bytes at %d --> %d\n",
+		count, offset, (int) status);
+
+	mutex_unlock(&at25->lock);
+	return status ? status : count;
+}
+
+static ssize_t
+at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct device		*dev;
+	struct at25_data	*at25;
+
+	dev = container_of(kobj, struct device, kobj);
+	at25 = dev_get_drvdata(dev);
+
+	if (unlikely(off >= at25->bin.size))
+		return 0;
+	if ((off + count) > at25->bin.size)
+		count = at25->bin.size - off;
+	if (unlikely(!count))
+		return count;
+
+	return at25_ee_read(at25, buf, off, count);
+}
+
+
+static ssize_t
+at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count)
+{
+	ssize_t			status = 0;
+	unsigned		written = 0;
+	unsigned		buf_size;
+	u8			*bounce;
+
+	/* Temp buffer starts with command and address */
+	buf_size = at25->chip.page_size;
+	if (buf_size > io_limit)
+		buf_size = io_limit;
+	bounce = kmalloc(buf_size + at25->addrlen + 1, GFP_KERNEL);
+	if (!bounce)
+		return -ENOMEM;
+
+	/* For write, rollover is within the page ... so we write at
+	 * most one page, then manually roll over to the next page.
+	 */
+	bounce[0] = AT25_WRITE;
+	mutex_lock(&at25->lock);
+	do {
+		unsigned long	timeout, retries;
+		unsigned	segment;
+		unsigned	offset = (unsigned) off;
+		u8		*cp = bounce + 1;
+
+		*cp = AT25_WREN;
+		status = spi_write(at25->spi, cp, 1);
+		if (status < 0) {
+			dev_dbg(&at25->spi->dev, "WREN --> %d\n",
+					(int) status);
+			break;
+		}
+
+		/* 8/16/24-bit address is written MSB first */
+		switch (at25->addrlen) {
+		default:	/* case 3 */
+			*cp++ = offset >> 16;
+		case 2:
+			*cp++ = offset >> 8;
+		case 1:
+		case 0:	/* can't happen: for better codegen */
+			*cp++ = offset >> 0;
+		}
+
+		/* Write as much of a page as we can */
+		segment = buf_size - (offset % buf_size);
+		if (segment > count)
+			segment = count;
+		memcpy(cp, buf, segment);
+		status = spi_write(at25->spi, bounce,
+				segment + at25->addrlen + 1);
+		dev_dbg(&at25->spi->dev,
+				"write %u bytes at %u --> %d\n",
+				segment, offset, (int) status);
+		if (status < 0)
+			break;
+
+		/* REVISIT this should detect (or prevent) failed writes
+		 * to readonly sections of the EEPROM...
+		 */
+
+		/* Wait for non-busy status */
+		timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT);
+		retries = 0;
+		do {
+			int	sr;
+
+			sr = spi_w8r8(at25->spi, AT25_RDSR);
+			if (sr < 0 || (sr & AT25_SR_nRDY)) {
+				dev_dbg(&at25->spi->dev,
+					"rdsr --> %d (%02x)\n", sr, sr);
+				/* at HZ=100, this is sloooow */
+				msleep(1);
+				continue;
+			}
+			if (!(sr & AT25_SR_nRDY))
+				break;
+		} while (retries++ < 3 || time_before_eq(jiffies, timeout));
+
+		if (time_after(jiffies, timeout)) {
+			dev_err(&at25->spi->dev,
+				"write %d bytes offset %d, "
+				"timeout after %u msecs\n",
+				segment, offset,
+				jiffies_to_msecs(jiffies -
+					(timeout - EE_TIMEOUT)));
+			status = -ETIMEDOUT;
+			break;
+		}
+
+		off += segment;
+		buf += segment;
+		count -= segment;
+		written += segment;
+
+	} while (count > 0);
+
+	mutex_unlock(&at25->lock);
+
+	kfree(bounce);
+	return written ? written : status;
+}
+
+static ssize_t
+at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct device		*dev;
+	struct at25_data	*at25;
+
+	dev = container_of(kobj, struct device, kobj);
+	at25 = dev_get_drvdata(dev);
+
+	if (unlikely(off >= at25->bin.size))
+		return -EFBIG;
+	if ((off + count) > at25->bin.size)
+		count = at25->bin.size - off;
+	if (unlikely(!count))
+		return count;
+
+	return at25_ee_write(at25, buf, off, count);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int at25_probe(struct spi_device *spi)
+{
+	struct at25_data	*at25 = NULL;
+	const struct spi_eeprom *chip;
+	int			err;
+	int			sr;
+	int			addrlen;
+
+	/* Chip description */
+	chip = spi->dev.platform_data;
+	if (!chip) {
+		dev_dbg(&spi->dev, "no chip description\n");
+		err = -ENODEV;
+		goto fail;
+	}
+
+	/* For now we only support 8/16/24 bit addressing */
+	if (chip->flags & EE_ADDR1)
+		addrlen = 1;
+	else if (chip->flags & EE_ADDR2)
+		addrlen = 2;
+	else if (chip->flags & EE_ADDR3)
+		addrlen = 3;
+	else {
+		dev_dbg(&spi->dev, "unsupported address type\n");
+		err = -EINVAL;
+		goto fail;
+	}
+
+	/* Ping the chip ... the status register is pretty portable,
+	 * unlike probing manufacturer IDs.  We do expect that system
+	 * firmware didn't write it in the past few milliseconds!
+	 */
+	sr = spi_w8r8(spi, AT25_RDSR);
+	if (sr < 0 || sr & AT25_SR_nRDY) {
+		dev_dbg(&at25->spi->dev, "rdsr --> %d (%02x)\n", sr, sr);
+		err = -ENXIO;
+		goto fail;
+	}
+
+	if (!(at25 = kzalloc(sizeof *at25, GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	mutex_init(&at25->lock);
+	at25->chip = *chip;
+	at25->spi = spi_dev_get(spi);
+	dev_set_drvdata(&spi->dev, at25);
+	at25->addrlen = addrlen;
+
+	/* Export the EEPROM bytes through sysfs, since that's convenient.
+	 * Default to root-only access to the data; EEPROMs often hold data
+	 * that's sensitive for read and/or write, like ethernet addresses,
+	 * security codes, board-specific manufacturing calibrations, etc.
+	 */
+	at25->bin.attr.name = "eeprom";
+	at25->bin.attr.mode = S_IRUSR;
+	at25->bin.attr.owner = THIS_MODULE;
+	at25->bin.read = at25_bin_read;
+
+	at25->bin.size = at25->chip.byte_len;
+	if (!(chip->flags & EE_READONLY)) {
+		at25->bin.write = at25_bin_write;
+		at25->bin.attr.mode |= S_IWUSR;
+	}
+
+	err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin);
+	if (err)
+		goto fail;
+
+	dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n",
+		(at25->bin.size < 1024)
+			? at25->bin.size
+			: (at25->bin.size / 1024),
+		(at25->bin.size < 1024) ? "Byte" : "KByte",
+		at25->chip.name,
+		(chip->flags & EE_READONLY) ? " (readonly)" : "",
+		at25->chip.page_size);
+	return 0;
+fail:
+	dev_dbg(&spi->dev, "probe err %d\n", err);
+	kfree(at25);
+	return err;
+}
+
+static int __devexit at25_remove(struct spi_device *spi)
+{
+	struct at25_data	*at25;
+
+	at25 = dev_get_drvdata(&spi->dev);
+	sysfs_remove_bin_file(&spi->dev.kobj, &at25->bin);
+	kfree(at25);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct spi_driver at25_driver = {
+	.driver = {
+		.name		= "at25",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= at25_probe,
+	.remove		= __devexit_p(at25_remove),
+};
+
+static int __init at25_init(void)
+{
+	return spi_register_driver(&at25_driver);
+}
+module_init(at25_init);
+
+static void __exit at25_exit(void)
+{
+	spi_unregister_driver(&at25_driver);
+}
+module_exit(at25_exit);
+
+MODULE_DESCRIPTION("Driver for most SPI EEPROMs");
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c
new file mode 100644
index 0000000..366af49
--- /dev/null
+++ b/drivers/spi/omap_uwire.c
@@ -0,0 +1,572 @@
+/*
+ * omap_uwire.c -- MicroWire interface driver for OMAP
+ *
+ * Copyright 2003 MontaVista Software Inc. <source@mvista.com>
+ *
+ * Ported to 2.6 OMAP uwire interface.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * Generalization patches by Juha Yrjola <juha.yrjola@nokia.com>
+ *
+ * Copyright (C) 2005 David Brownell (ported to 2.6 SPI interface)
+ * Copyright (C) 2006 Nokia
+ *
+ * Many updates by Imre Deak <imre.deak@nokia.com>
+ *
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/omap730.h>	/* OMAP730_IO_CONF registers */
+
+
+/* FIXME address is now a platform device resource,
+ * and irqs should show there too...
+ */
+#define UWIRE_BASE_PHYS		0xFFFB3000
+#define UWIRE_BASE		((void *__iomem)IO_ADDRESS(UWIRE_BASE_PHYS))
+
+/* uWire Registers: */
+#define UWIRE_IO_SIZE 0x20
+#define UWIRE_TDR     0x00
+#define UWIRE_RDR     0x00
+#define UWIRE_CSR     0x01
+#define UWIRE_SR1     0x02
+#define UWIRE_SR2     0x03
+#define UWIRE_SR3     0x04
+#define UWIRE_SR4     0x05
+#define UWIRE_SR5     0x06
+
+/* CSR bits */
+#define	RDRB	(1 << 15)
+#define	CSRB	(1 << 14)
+#define	START	(1 << 13)
+#define	CS_CMD	(1 << 12)
+
+/* SR1 or SR2 bits */
+#define UWIRE_READ_FALLING_EDGE		0x0001
+#define UWIRE_READ_RISING_EDGE		0x0000
+#define UWIRE_WRITE_FALLING_EDGE	0x0000
+#define UWIRE_WRITE_RISING_EDGE		0x0002
+#define UWIRE_CS_ACTIVE_LOW		0x0000
+#define UWIRE_CS_ACTIVE_HIGH		0x0004
+#define UWIRE_FREQ_DIV_2		0x0000
+#define UWIRE_FREQ_DIV_4		0x0008
+#define UWIRE_FREQ_DIV_8		0x0010
+#define UWIRE_CHK_READY			0x0020
+#define UWIRE_CLK_INVERTED		0x0040
+
+
+struct uwire_spi {
+	struct spi_bitbang	bitbang;
+	struct clk		*ck;
+};
+
+struct uwire_state {
+	unsigned	bits_per_word;
+	unsigned	div1_idx;
+};
+
+/* REVISIT compile time constant for idx_shift? */
+static unsigned int uwire_idx_shift;
+
+static inline void uwire_write_reg(int idx, u16 val)
+{
+	__raw_writew(val, UWIRE_BASE + (idx << uwire_idx_shift));
+}
+
+static inline u16 uwire_read_reg(int idx)
+{
+	return __raw_readw(UWIRE_BASE + (idx << uwire_idx_shift));
+}
+
+static inline void omap_uwire_configure_mode(u8 cs, unsigned long flags)
+{
+	u16	w, val = 0;
+	int	shift, reg;
+
+	if (flags & UWIRE_CLK_INVERTED)
+		val ^= 0x03;
+	val = flags & 0x3f;
+	if (cs & 1)
+		shift = 6;
+	else
+		shift = 0;
+	if (cs <= 1)
+		reg = UWIRE_SR1;
+	else
+		reg = UWIRE_SR2;
+
+	w = uwire_read_reg(reg);
+	w &= ~(0x3f << shift);
+	w |= val << shift;
+	uwire_write_reg(reg, w);
+}
+
+static int wait_uwire_csr_flag(u16 mask, u16 val, int might_not_catch)
+{
+	u16 w;
+	int c = 0;
+	unsigned long max_jiffies = jiffies + HZ;
+
+	for (;;) {
+		w = uwire_read_reg(UWIRE_CSR);
+		if ((w & mask) == val)
+			break;
+		if (time_after(jiffies, max_jiffies)) {
+			printk(KERN_ERR "%s: timeout. reg=%#06x "
+					"mask=%#06x val=%#06x\n",
+			       __FUNCTION__, w, mask, val);
+			return -1;
+		}
+		c++;
+		if (might_not_catch && c > 64)
+			break;
+	}
+	return 0;
+}
+
+static void uwire_set_clk1_div(int div1_idx)
+{
+	u16 w;
+
+	w = uwire_read_reg(UWIRE_SR3);
+	w &= ~(0x03 << 1);
+	w |= div1_idx << 1;
+	uwire_write_reg(UWIRE_SR3, w);
+}
+
+static void uwire_chipselect(struct spi_device *spi, int value)
+{
+	struct	uwire_state *ust = spi->controller_state;
+	u16	w;
+	int	old_cs;
+
+
+	BUG_ON(wait_uwire_csr_flag(CSRB, 0, 0));
+
+	w = uwire_read_reg(UWIRE_CSR);
+	old_cs = (w >> 10) & 0x03;
+	if (value == BITBANG_CS_INACTIVE || old_cs != spi->chip_select) {
+		/* Deselect this CS, or the previous CS */
+		w &= ~CS_CMD;
+		uwire_write_reg(UWIRE_CSR, w);
+	}
+	/* activate specfied chipselect */
+	if (value == BITBANG_CS_ACTIVE) {
+		uwire_set_clk1_div(ust->div1_idx);
+		/* invert clock? */
+		if (spi->mode & SPI_CPOL)
+			uwire_write_reg(UWIRE_SR4, 1);
+		else
+			uwire_write_reg(UWIRE_SR4, 0);
+
+		w = spi->chip_select << 10;
+		w |= CS_CMD;
+		uwire_write_reg(UWIRE_CSR, w);
+	}
+}
+
+static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct uwire_state *ust = spi->controller_state;
+	unsigned	len = t->len;
+	unsigned	bits = ust->bits_per_word;
+	unsigned	bytes;
+	u16		val, w;
+	int		status = 0;;
+
+	if (!t->tx_buf && !t->rx_buf)
+		return 0;
+
+	/* Microwire doesn't read and write concurrently */
+	if (t->tx_buf && t->rx_buf)
+		return -EPERM;
+
+	w = spi->chip_select << 10;
+	w |= CS_CMD;
+
+	if (t->tx_buf) {
+		const u8	*buf = t->tx_buf;
+
+		/* NOTE:  DMA could be used for TX transfers */
+
+		/* write one or two bytes at a time */
+		while (len >= 1) {
+			/* tx bit 15 is first sent; we byteswap multibyte words
+			 * (msb-first) on the way out from memory.
+			 */
+			val = *buf++;
+			if (bits > 8) {
+				bytes = 2;
+				val |= *buf++ << 8;
+			} else
+				bytes = 1;
+			val <<= 16 - bits;
+
+#ifdef	VERBOSE
+			pr_debug("%s: write-%d =%04x\n",
+					spi->dev.bus_id, bits, val);
+#endif
+			if (wait_uwire_csr_flag(CSRB, 0, 0))
+				goto eio;
+
+			uwire_write_reg(UWIRE_TDR, val);
+
+			/* start write */
+			val = START | w | (bits << 5);
+
+			uwire_write_reg(UWIRE_CSR, val);
+			len -= bytes;
+
+			/* Wait till write actually starts.
+			 * This is needed with MPU clock 60+ MHz.
+			 * REVISIT: we may not have time to catch it...
+			 */
+			if (wait_uwire_csr_flag(CSRB, CSRB, 1))
+				goto eio;
+
+			status += bytes;
+		}
+
+		/* REVISIT:  save this for later to get more i/o overlap */
+		if (wait_uwire_csr_flag(CSRB, 0, 0))
+			goto eio;
+
+	} else if (t->rx_buf) {
+		u8		*buf = t->rx_buf;
+
+		/* read one or two bytes at a time */
+		while (len) {
+			if (bits > 8) {
+				bytes = 2;
+			} else
+				bytes = 1;
+
+			/* start read */
+			val = START | w | (bits << 0);
+			uwire_write_reg(UWIRE_CSR, val);
+			len -= bytes;
+
+			/* Wait till read actually starts */
+			(void) wait_uwire_csr_flag(CSRB, CSRB, 1);
+
+			if (wait_uwire_csr_flag(RDRB | CSRB,
+						RDRB, 0))
+				goto eio;
+
+			/* rx bit 0 is last received; multibyte words will
+			 * be properly byteswapped on the way to memory.
+			 */
+			val = uwire_read_reg(UWIRE_RDR);
+			val &= (1 << bits) - 1;
+			*buf++ = (u8) val;
+			if (bytes == 2)
+				*buf++ = val >> 8;
+			status += bytes;
+#ifdef	VERBOSE
+			pr_debug("%s: read-%d =%04x\n",
+					spi->dev.bus_id, bits, val);
+#endif
+
+		}
+	}
+	return status;
+eio:
+	return -EIO;
+}
+
+static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct uwire_state	*ust = spi->controller_state;
+	struct uwire_spi	*uwire;
+	unsigned		flags = 0;
+	unsigned		bits;
+	unsigned		hz;
+	unsigned long		rate;
+	int			div1_idx;
+	int			div1;
+	int			div2;
+	int			status;
+
+	uwire = spi_master_get_devdata(spi->master);
+
+	if (spi->chip_select > 3) {
+		pr_debug("%s: cs%d?\n", spi->dev.bus_id, spi->chip_select);
+		status = -ENODEV;
+		goto done;
+	}
+
+	bits = spi->bits_per_word;
+	if (t != NULL && t->bits_per_word)
+		bits = t->bits_per_word;
+	if (!bits)
+		bits = 8;
+
+	if (bits > 16) {
+		pr_debug("%s: wordsize %d?\n", spi->dev.bus_id, bits);
+		status = -ENODEV;
+		goto done;
+	}
+	ust->bits_per_word = bits;
+
+	/* mode 0..3, clock inverted separately;
+	 * standard nCS signaling;
+	 * don't treat DI=high as "not ready"
+	 */
+	if (spi->mode & SPI_CS_HIGH)
+		flags |= UWIRE_CS_ACTIVE_HIGH;
+
+	if (spi->mode & SPI_CPOL)
+		flags |= UWIRE_CLK_INVERTED;
+
+	switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
+	case SPI_MODE_0:
+	case SPI_MODE_3:
+		flags |= UWIRE_WRITE_RISING_EDGE | UWIRE_READ_FALLING_EDGE;
+		break;
+	case SPI_MODE_1:
+	case SPI_MODE_2:
+		flags |= UWIRE_WRITE_FALLING_EDGE | UWIRE_READ_RISING_EDGE;
+		break;
+	}
+
+	/* assume it's already enabled */
+	rate = clk_get_rate(uwire->ck);
+
+	hz = spi->max_speed_hz;
+	if (t != NULL && t->speed_hz)
+		hz = t->speed_hz;
+
+	if (!hz) {
+		pr_debug("%s: zero speed?\n", spi->dev.bus_id);
+		status = -EINVAL;
+		goto done;
+	}
+
+	/* F_INT = mpu_xor_clk / DIV1 */
+	for (div1_idx = 0; div1_idx < 4; div1_idx++) {
+		switch (div1_idx) {
+		case 0:
+			div1 = 2;
+			break;
+		case 1:
+			div1 = 4;
+			break;
+		case 2:
+			div1 = 7;
+			break;
+		default:
+		case 3:
+			div1 = 10;
+			break;
+		}
+		div2 = (rate / div1 + hz - 1) / hz;
+		if (div2 <= 8)
+			break;
+	}
+	if (div1_idx == 4) {
+		pr_debug("%s: lowest clock %ld, need %d\n",
+			spi->dev.bus_id, rate / 10 / 8, hz);
+		status = -EDOM;
+		goto done;
+	}
+
+	/* we have to cache this and reset in uwire_chipselect as this is a
+	 * global parameter and another uwire device can change it under
+	 * us */
+	ust->div1_idx = div1_idx;
+	uwire_set_clk1_div(div1_idx);
+
+	rate /= div1;
+
+	switch (div2) {
+	case 0:
+	case 1:
+	case 2:
+		flags |= UWIRE_FREQ_DIV_2;
+		rate /= 2;
+		break;
+	case 3:
+	case 4:
+		flags |= UWIRE_FREQ_DIV_4;
+		rate /= 4;
+		break;
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+		flags |= UWIRE_FREQ_DIV_8;
+		rate /= 8;
+		break;
+	}
+	omap_uwire_configure_mode(spi->chip_select, flags);
+	pr_debug("%s: uwire flags %02x, armxor %lu KHz, SCK %lu KHz\n",
+			__FUNCTION__, flags,
+			clk_get_rate(uwire->ck) / 1000,
+			rate / 1000);
+	status = 0;
+done:
+	return status;
+}
+
+static int uwire_setup(struct spi_device *spi)
+{
+	struct uwire_state *ust = spi->controller_state;
+
+	if (ust == NULL) {
+		ust = kzalloc(sizeof(*ust), GFP_KERNEL);
+		if (ust == NULL)
+			return -ENOMEM;
+		spi->controller_state = ust;
+	}
+
+	return uwire_setup_transfer(spi, NULL);
+}
+
+static void uwire_cleanup(const struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static void uwire_off(struct uwire_spi *uwire)
+{
+	uwire_write_reg(UWIRE_SR3, 0);
+	clk_disable(uwire->ck);
+	clk_put(uwire->ck);
+	spi_master_put(uwire->bitbang.master);
+}
+
+static int uwire_probe(struct platform_device *pdev)
+{
+	struct spi_master	*master;
+	struct uwire_spi	*uwire;
+	int			status;
+
+	master = spi_alloc_master(&pdev->dev, sizeof *uwire);
+	if (!master)
+		return -ENODEV;
+
+	uwire = spi_master_get_devdata(master);
+	dev_set_drvdata(&pdev->dev, uwire);
+
+	uwire->ck = clk_get(&pdev->dev, "armxor_ck");
+	if (!uwire->ck || IS_ERR(uwire->ck)) {
+		dev_dbg(&pdev->dev, "no mpu_xor_clk ?\n");
+		spi_master_put(master);
+		return -ENODEV;
+	}
+	clk_enable(uwire->ck);
+
+	if (cpu_is_omap730())
+		uwire_idx_shift = 1;
+	else
+		uwire_idx_shift = 2;
+
+	uwire_write_reg(UWIRE_SR3, 1);
+
+	master->bus_num = 2;	/* "official" */
+	master->num_chipselect = 4;
+	master->setup = uwire_setup;
+	master->cleanup = uwire_cleanup;
+
+	uwire->bitbang.master = master;
+	uwire->bitbang.chipselect = uwire_chipselect;
+	uwire->bitbang.setup_transfer = uwire_setup_transfer;
+	uwire->bitbang.txrx_bufs = uwire_txrx;
+
+	status = spi_bitbang_start(&uwire->bitbang);
+	if (status < 0)
+		uwire_off(uwire);
+	return status;
+}
+
+static int uwire_remove(struct platform_device *pdev)
+{
+	struct uwire_spi	*uwire = dev_get_drvdata(&pdev->dev);
+	int			status;
+
+	// FIXME remove all child devices, somewhere ...
+
+	status = spi_bitbang_stop(&uwire->bitbang);
+	uwire_off(uwire);
+	return status;
+}
+
+static struct platform_driver uwire_driver = {
+	.driver = {
+		.name		= "omap_uwire",
+		.bus		= &platform_bus_type,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= uwire_probe,
+	.remove		= uwire_remove,
+	// suspend ... unuse ck
+	// resume ... use ck
+};
+
+static int __init omap_uwire_init(void)
+{
+	/* FIXME move these into the relevant board init code. also, include
+	 * H3 support; it uses tsc2101 like H2 (on a different chipselect).
+	 */
+
+	if (machine_is_omap_h2()) {
+		/* defaults: W21 SDO, U18 SDI, V19 SCL */
+		omap_cfg_reg(N14_1610_UWIRE_CS0);
+		omap_cfg_reg(N15_1610_UWIRE_CS1);
+	}
+	if (machine_is_omap_perseus2()) {
+		/* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */
+		int val = omap_readl(OMAP730_IO_CONF_9) & ~0x00EEE000;
+		omap_writel(val | 0x00AAA000, OMAP730_IO_CONF_9);
+	}
+
+	return platform_driver_register(&uwire_driver);
+}
+
+static void __exit omap_uwire_exit(void)
+{
+	platform_driver_unregister(&uwire_driver);
+}
+
+subsys_initcall(omap_uwire_init);
+module_exit(omap_uwire_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 8b41f9c..9f2c887 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1214,9 +1214,9 @@
 	return 0;
 }
 
-static void cleanup(const struct spi_device *spi)
+static void cleanup(struct spi_device *spi)
 {
-	struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
+	struct chip_data *chip = spi_get_ctldata(spi);
 
 	kfree(chip);
 }
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 6307428..2328128 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -32,7 +32,7 @@
  */
 static void spidev_release(struct device *dev)
 {
-	const struct spi_device	*spi = to_spi_device(dev);
+	struct spi_device	*spi = to_spi_device(dev);
 
 	/* spi masters may cleanup for released devices */
 	if (spi->master->cleanup)
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 57289b6..24a330d 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -210,7 +210,7 @@
 	if (!cs->txrx_word)
 		return -EINVAL;
 
-	retval = spi_bitbang_setup_transfer(spi, NULL);
+	retval = bitbang->setup_transfer(spi, NULL);
 	if (retval < 0)
 		return retval;
 
@@ -238,7 +238,7 @@
 /**
  * spi_bitbang_cleanup - default cleanup for per-word I/O loops
  */
-void spi_bitbang_cleanup(const struct spi_device *spi)
+void spi_bitbang_cleanup(struct spi_device *spi)
 {
 	kfree(spi->controller_state);
 }
@@ -442,9 +442,10 @@
  * hardware that basically exposes a shift register) or per-spi_transfer
  * (which takes better advantage of hardware like fifos or DMA engines).
  *
- * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and
- * spi_bitbang_cleanup to handle those spi master methods.  Those methods are
- * the defaults if the bitbang->txrx_bufs routine isn't initialized.
+ * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup,
+ * spi_bitbang_cleanup and spi_bitbang_setup_transfer to handle those spi
+ * master methods.  Those methods are the defaults if the bitbang->txrx_bufs
+ * routine isn't initialized.
  *
  * This routine registers the spi_master, which will process requests in a
  * dedicated task, keeping IRQs unblocked most of the time.  To stop
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
new file mode 100644
index 0000000..6ccf8a1
--- /dev/null
+++ b/drivers/spi/spi_imx.c
@@ -0,0 +1,1769 @@
+/*
+ * drivers/spi/spi_imx.c
+ *
+ * Copyright (C) 2006 SWAPP
+ *	Andrea Paterniani <a.paterniani@swapp-eng.it>
+ *
+ * Initial version inspired by:
+ *	linux-2.6.17-rc3-mm1/drivers/spi/pxa2xx_spi.c
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/spi.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/delay.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/imx-dma.h>
+#include <asm/arch/spi_imx.h>
+
+/*-------------------------------------------------------------------------*/
+/* SPI Registers offsets from peripheral base address */
+#define SPI_RXDATA		(0x00)
+#define SPI_TXDATA		(0x04)
+#define SPI_CONTROL		(0x08)
+#define SPI_INT_STATUS		(0x0C)
+#define SPI_TEST		(0x10)
+#define SPI_PERIOD		(0x14)
+#define SPI_DMA			(0x18)
+#define SPI_RESET		(0x1C)
+
+/* SPI Control Register Bit Fields & Masks */
+#define SPI_CONTROL_BITCOUNT_MASK	(0xF)		/* Bit Count Mask */
+#define SPI_CONTROL_BITCOUNT(n)		(((n) - 1) & SPI_CONTROL_BITCOUNT_MASK)
+#define SPI_CONTROL_POL			(0x1 << 4)      /* Clock Polarity Mask */
+#define SPI_CONTROL_POL_ACT_HIGH	(0x0 << 4)      /* Active high pol. (0=idle) */
+#define SPI_CONTROL_POL_ACT_LOW		(0x1 << 4)      /* Active low pol. (1=idle) */
+#define SPI_CONTROL_PHA			(0x1 << 5)      /* Clock Phase Mask */
+#define SPI_CONTROL_PHA_0		(0x0 << 5)      /* Clock Phase 0 */
+#define SPI_CONTROL_PHA_1		(0x1 << 5)      /* Clock Phase 1 */
+#define SPI_CONTROL_SSCTL		(0x1 << 6)      /* /SS Waveform Select Mask */
+#define SPI_CONTROL_SSCTL_0		(0x0 << 6)      /* Master: /SS stays low between SPI burst
+							   Slave: RXFIFO advanced by BIT_COUNT */
+#define SPI_CONTROL_SSCTL_1		(0x1 << 6)      /* Master: /SS insert pulse between SPI burst
+							   Slave: RXFIFO advanced by /SS rising edge */
+#define SPI_CONTROL_SSPOL		(0x1 << 7)      /* /SS Polarity Select Mask */
+#define SPI_CONTROL_SSPOL_ACT_LOW	(0x0 << 7)      /* /SS Active low */
+#define SPI_CONTROL_SSPOL_ACT_HIGH	(0x1 << 7)      /* /SS Active high */
+#define SPI_CONTROL_XCH			(0x1 << 8)      /* Exchange */
+#define SPI_CONTROL_SPIEN		(0x1 << 9)      /* SPI Module Enable */
+#define SPI_CONTROL_MODE		(0x1 << 10)     /* SPI Mode Select Mask */
+#define SPI_CONTROL_MODE_SLAVE		(0x0 << 10)     /* SPI Mode Slave */
+#define SPI_CONTROL_MODE_MASTER		(0x1 << 10)     /* SPI Mode Master */
+#define SPI_CONTROL_DRCTL		(0x3 << 11)     /* /SPI_RDY Control Mask */
+#define SPI_CONTROL_DRCTL_0		(0x0 << 11)     /* Ignore /SPI_RDY */
+#define SPI_CONTROL_DRCTL_1		(0x1 << 11)     /* /SPI_RDY falling edge triggers input */
+#define SPI_CONTROL_DRCTL_2		(0x2 << 11)     /* /SPI_RDY active low level triggers input */
+#define SPI_CONTROL_DATARATE		(0x7 << 13)     /* Data Rate Mask */
+#define SPI_PERCLK2_DIV_MIN		(0)		/* PERCLK2:4 */
+#define SPI_PERCLK2_DIV_MAX		(7)		/* PERCLK2:512 */
+#define SPI_CONTROL_DATARATE_MIN	(SPI_PERCLK2_DIV_MAX << 13)
+#define SPI_CONTROL_DATARATE_MAX	(SPI_PERCLK2_DIV_MIN << 13)
+#define SPI_CONTROL_DATARATE_BAD	(SPI_CONTROL_DATARATE_MIN + 1)
+
+/* SPI Interrupt/Status Register Bit Fields & Masks */
+#define SPI_STATUS_TE	(0x1 << 0)	/* TXFIFO Empty Status */
+#define SPI_STATUS_TH	(0x1 << 1)      /* TXFIFO Half Status */
+#define SPI_STATUS_TF	(0x1 << 2)      /* TXFIFO Full Status */
+#define SPI_STATUS_RR	(0x1 << 3)      /* RXFIFO Data Ready Status */
+#define SPI_STATUS_RH	(0x1 << 4)      /* RXFIFO Half Status */
+#define SPI_STATUS_RF	(0x1 << 5)      /* RXFIFO Full Status */
+#define SPI_STATUS_RO	(0x1 << 6)      /* RXFIFO Overflow */
+#define SPI_STATUS_BO	(0x1 << 7)      /* Bit Count Overflow */
+#define SPI_STATUS	(0xFF)		/* SPI Status Mask */
+#define SPI_INTEN_TE	(0x1 << 8)      /* TXFIFO Empty Interrupt Enable */
+#define SPI_INTEN_TH	(0x1 << 9)      /* TXFIFO Half Interrupt Enable */
+#define SPI_INTEN_TF	(0x1 << 10)     /* TXFIFO Full Interrupt Enable */
+#define SPI_INTEN_RE	(0x1 << 11)     /* RXFIFO Data Ready Interrupt Enable */
+#define SPI_INTEN_RH	(0x1 << 12)     /* RXFIFO Half Interrupt Enable */
+#define SPI_INTEN_RF	(0x1 << 13)     /* RXFIFO Full Interrupt Enable */
+#define SPI_INTEN_RO	(0x1 << 14)     /* RXFIFO Overflow Interrupt Enable */
+#define SPI_INTEN_BO	(0x1 << 15)     /* Bit Count Overflow Interrupt Enable */
+#define SPI_INTEN	(0xFF << 8)	/* SPI Interrupt Enable Mask */
+
+/* SPI Test Register Bit Fields & Masks */
+#define SPI_TEST_TXCNT		(0xF << 0)	/* TXFIFO Counter */
+#define SPI_TEST_RXCNT_LSB	(4)		/* RXFIFO Counter LSB */
+#define SPI_TEST_RXCNT		(0xF << 4)	/* RXFIFO Counter */
+#define SPI_TEST_SSTATUS	(0xF << 8)	/* State Machine Status */
+#define SPI_TEST_LBC		(0x1 << 14)	/* Loop Back Control */
+
+/* SPI Period Register Bit Fields & Masks */
+#define SPI_PERIOD_WAIT		(0x7FFF << 0)	/* Wait Between Transactions */
+#define SPI_PERIOD_MAX_WAIT	(0x7FFF)	/* Max Wait Between
+							Transactions */
+#define SPI_PERIOD_CSRC		(0x1 << 15)	/* Period Clock Source Mask */
+#define SPI_PERIOD_CSRC_BCLK	(0x0 << 15)	/* Period Clock Source is
+							Bit Clock */
+#define SPI_PERIOD_CSRC_32768	(0x1 << 15)	/* Period Clock Source is
+							32.768 KHz Clock */
+
+/* SPI DMA Register Bit Fields & Masks */
+#define SPI_DMA_RHDMA	(0xF << 4)	/* RXFIFO Half Status */
+#define SPI_DMA_RFDMA	(0x1 << 5)      /* RXFIFO Full Status */
+#define SPI_DMA_TEDMA	(0x1 << 6)      /* TXFIFO Empty Status */
+#define SPI_DMA_THDMA	(0x1 << 7)      /* TXFIFO Half Status */
+#define SPI_DMA_RHDEN	(0x1 << 12)	/* RXFIFO Half DMA Request Enable */
+#define SPI_DMA_RFDEN	(0x1 << 13)     /* RXFIFO Full DMA Request Enable */
+#define SPI_DMA_TEDEN	(0x1 << 14)     /* TXFIFO Empty DMA Request Enable */
+#define SPI_DMA_THDEN	(0x1 << 15)     /* TXFIFO Half DMA Request Enable */
+
+/* SPI Soft Reset Register Bit Fields & Masks */
+#define SPI_RESET_START	(0x1)		/* Start */
+
+/* Default SPI configuration values */
+#define SPI_DEFAULT_CONTROL		\
+(					\
+	SPI_CONTROL_BITCOUNT(16) | 	\
+	SPI_CONTROL_POL_ACT_HIGH |	\
+	SPI_CONTROL_PHA_0 |		\
+	SPI_CONTROL_SPIEN |		\
+	SPI_CONTROL_SSCTL_1 |		\
+	SPI_CONTROL_MODE_MASTER |	\
+	SPI_CONTROL_DRCTL_0 |		\
+	SPI_CONTROL_DATARATE_MIN	\
+)
+#define SPI_DEFAULT_ENABLE_LOOPBACK	(0)
+#define SPI_DEFAULT_ENABLE_DMA		(0)
+#define SPI_DEFAULT_PERIOD_WAIT		(8)
+/*-------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/* TX/RX SPI FIFO size */
+#define SPI_FIFO_DEPTH			(8)
+#define SPI_FIFO_BYTE_WIDTH		(2)
+#define SPI_FIFO_OVERFLOW_MARGIN	(2)
+
+/* DMA burst lenght for half full/empty request trigger */
+#define SPI_DMA_BLR			(SPI_FIFO_DEPTH * SPI_FIFO_BYTE_WIDTH / 2)
+
+/* Dummy char output to achieve reads.
+   Choosing something different from all zeroes may help pattern recogition
+   for oscilloscope analysis, but may break some drivers. */
+#define SPI_DUMMY_u8			0
+#define SPI_DUMMY_u16			((SPI_DUMMY_u8 << 8) | SPI_DUMMY_u8)
+#define SPI_DUMMY_u32			((SPI_DUMMY_u16 << 16) | SPI_DUMMY_u16)
+
+/**
+ * Macro to change a u32 field:
+ * @r : register to edit
+ * @m : bit mask
+ * @v : new value for the field correctly bit-alligned
+*/
+#define u32_EDIT(r, m, v)		r = (r & ~(m)) | (v)
+
+/* Message state */
+#define START_STATE			((void*)0)
+#define RUNNING_STATE			((void*)1)
+#define DONE_STATE			((void*)2)
+#define ERROR_STATE			((void*)-1)
+
+/* Queue state */
+#define QUEUE_RUNNING			(0)
+#define QUEUE_STOPPED			(1)
+
+#define IS_DMA_ALIGNED(x) 		(((u32)(x) & 0x03) == 0)
+/*-------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/* Driver data structs */
+
+/* Context */
+struct driver_data {
+	/* Driver model hookup */
+	struct platform_device *pdev;
+
+	/* SPI framework hookup */
+	struct spi_master *master;
+
+	/* IMX hookup */
+	struct spi_imx_master *master_info;
+
+	/* Memory resources and SPI regs virtual address */
+	struct resource *ioarea;
+	void __iomem *regs;
+
+	/* SPI RX_DATA physical address */
+	dma_addr_t rd_data_phys;
+
+	/* Driver message queue */
+	struct workqueue_struct	*workqueue;
+	struct work_struct work;
+	spinlock_t lock;
+	struct list_head queue;
+	int busy;
+	int run;
+
+	/* Message Transfer pump */
+	struct tasklet_struct pump_transfers;
+
+	/* Current message, transfer and state */
+	struct spi_message *cur_msg;
+	struct spi_transfer *cur_transfer;
+	struct chip_data *cur_chip;
+
+	/* Rd / Wr buffers pointers */
+	size_t len;
+	void *tx;
+	void *tx_end;
+	void *rx;
+	void *rx_end;
+
+	u8 rd_only;
+	u8 n_bytes;
+	int cs_change;
+
+	/* Function pointers */
+	irqreturn_t (*transfer_handler)(struct driver_data *drv_data);
+	void (*cs_control)(u32 command);
+
+	/* DMA setup */
+	int rx_channel;
+	int tx_channel;
+	dma_addr_t rx_dma;
+	dma_addr_t tx_dma;
+	int rx_dma_needs_unmap;
+	int tx_dma_needs_unmap;
+	size_t tx_map_len;
+	u32 dummy_dma_buf ____cacheline_aligned;
+};
+
+/* Runtime state */
+struct chip_data {
+	u32 control;
+	u32 period;
+	u32 test;
+
+	u8 enable_dma:1;
+	u8 bits_per_word;
+	u8 n_bytes;
+	u32 max_speed_hz;
+
+	void (*cs_control)(u32 command);
+};
+/*-------------------------------------------------------------------------*/
+
+
+static void pump_messages(struct work_struct *work);
+
+static int flush(struct driver_data *drv_data)
+{
+	unsigned long limit = loops_per_jiffy << 1;
+	void __iomem *regs = drv_data->regs;
+	volatile u32 d;
+
+	dev_dbg(&drv_data->pdev->dev, "flush\n");
+	do {
+		while (readl(regs + SPI_INT_STATUS) & SPI_STATUS_RR)
+			d = readl(regs + SPI_RXDATA);
+	} while ((readl(regs + SPI_CONTROL) & SPI_CONTROL_XCH) && limit--);
+
+	return limit;
+}
+
+static void restore_state(struct driver_data *drv_data)
+{
+	void __iomem *regs = drv_data->regs;
+	struct chip_data *chip = drv_data->cur_chip;
+
+	/* Load chip registers */
+	dev_dbg(&drv_data->pdev->dev,
+		"restore_state\n"
+		"    test    = 0x%08X\n"
+		"    control = 0x%08X\n",
+		chip->test,
+		chip->control);
+	writel(chip->test, regs + SPI_TEST);
+	writel(chip->period, regs + SPI_PERIOD);
+	writel(0, regs + SPI_INT_STATUS);
+	writel(chip->control, regs + SPI_CONTROL);
+}
+
+static void null_cs_control(u32 command)
+{
+}
+
+static inline u32 data_to_write(struct driver_data *drv_data)
+{
+	return ((u32)(drv_data->tx_end - drv_data->tx)) / drv_data->n_bytes;
+}
+
+static inline u32 data_to_read(struct driver_data *drv_data)
+{
+	return ((u32)(drv_data->rx_end - drv_data->rx)) / drv_data->n_bytes;
+}
+
+static int write(struct driver_data *drv_data)
+{
+	void __iomem *regs = drv_data->regs;
+	void *tx = drv_data->tx;
+	void *tx_end = drv_data->tx_end;
+	u8 n_bytes = drv_data->n_bytes;
+	u32 remaining_writes;
+	u32 fifo_avail_space;
+	u32 n;
+	u16 d;
+
+	/* Compute how many fifo writes to do */
+	remaining_writes = (u32)(tx_end - tx) / n_bytes;
+	fifo_avail_space = SPI_FIFO_DEPTH -
+				(readl(regs + SPI_TEST) & SPI_TEST_TXCNT);
+	if (drv_data->rx && (fifo_avail_space > SPI_FIFO_OVERFLOW_MARGIN))
+		/* Fix misunderstood receive overflow */
+		fifo_avail_space -= SPI_FIFO_OVERFLOW_MARGIN;
+	n = min(remaining_writes, fifo_avail_space);
+
+	dev_dbg(&drv_data->pdev->dev,
+		"write type %s\n"
+		"    remaining writes = %d\n"
+		"    fifo avail space = %d\n"
+		"    fifo writes      = %d\n",
+		(n_bytes == 1) ? "u8" : "u16",
+		remaining_writes,
+		fifo_avail_space,
+		n);
+
+	if (n > 0) {
+		/* Fill SPI TXFIFO */
+		if (drv_data->rd_only) {
+			tx += n * n_bytes;
+			while (n--)
+				writel(SPI_DUMMY_u16, regs + SPI_TXDATA);
+		} else {
+			if (n_bytes == 1) {
+				while (n--) {
+					d = *(u8*)tx;
+					writel(d, regs + SPI_TXDATA);
+					tx += 1;
+				}
+			} else {
+				while (n--) {
+					d = *(u16*)tx;
+					writel(d, regs + SPI_TXDATA);
+					tx += 2;
+				}
+			}
+		}
+
+		/* Trigger transfer */
+		writel(readl(regs + SPI_CONTROL) | SPI_CONTROL_XCH,
+			regs + SPI_CONTROL);
+
+		/* Update tx pointer */
+		drv_data->tx = tx;
+	}
+
+	return (tx >= tx_end);
+}
+
+static int read(struct driver_data *drv_data)
+{
+	void __iomem *regs = drv_data->regs;
+	void *rx = drv_data->rx;
+	void *rx_end = drv_data->rx_end;
+	u8 n_bytes = drv_data->n_bytes;
+	u32 remaining_reads;
+	u32 fifo_rxcnt;
+	u32 n;
+	u16 d;
+
+	/* Compute how many fifo reads to do */
+	remaining_reads = (u32)(rx_end - rx) / n_bytes;
+	fifo_rxcnt = (readl(regs + SPI_TEST) & SPI_TEST_RXCNT) >>
+			SPI_TEST_RXCNT_LSB;
+	n = min(remaining_reads, fifo_rxcnt);
+
+	dev_dbg(&drv_data->pdev->dev,
+		"read type %s\n"
+		"    remaining reads = %d\n"
+		"    fifo rx count   = %d\n"
+		"    fifo reads      = %d\n",
+		(n_bytes == 1) ? "u8" : "u16",
+		remaining_reads,
+		fifo_rxcnt,
+		n);
+
+	if (n > 0) {
+		/* Read SPI RXFIFO */
+		if (n_bytes == 1) {
+			while (n--) {
+				d = readl(regs + SPI_RXDATA);
+				*((u8*)rx) = d;
+				rx += 1;
+			}
+		} else {
+			while (n--) {
+				d = readl(regs + SPI_RXDATA);
+				*((u16*)rx) = d;
+				rx += 2;
+			}
+		}
+
+		/* Update rx pointer */
+		drv_data->rx = rx;
+	}
+
+	return (rx >= rx_end);
+}
+
+static void *next_transfer(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct spi_transfer *trans = drv_data->cur_transfer;
+
+	/* Move to next transfer */
+	if (trans->transfer_list.next != &msg->transfers) {
+		drv_data->cur_transfer =
+			list_entry(trans->transfer_list.next,
+					struct spi_transfer,
+					transfer_list);
+		return RUNNING_STATE;
+	}
+
+	return DONE_STATE;
+}
+
+static int map_dma_buffers(struct driver_data *drv_data)
+{
+	struct spi_message *msg;
+	struct device *dev;
+	void *buf;
+
+	drv_data->rx_dma_needs_unmap = 0;
+	drv_data->tx_dma_needs_unmap = 0;
+
+	if (!drv_data->master_info->enable_dma ||
+		!drv_data->cur_chip->enable_dma)
+			return -1;
+
+	msg = drv_data->cur_msg;
+	dev = &msg->spi->dev;
+	if (msg->is_dma_mapped) {
+		if (drv_data->tx_dma)
+			/* The caller provided at least dma and cpu virtual
+			   address for write; pump_transfers() will consider the
+			   transfer as write only if cpu rx virtual address is
+			   NULL */
+			return 0;
+
+		if (drv_data->rx_dma) {
+			/* The caller provided dma and cpu virtual address to
+			   performe read only transfer -->
+			   use drv_data->dummy_dma_buf for dummy writes to
+			   achive reads */
+			buf = &drv_data->dummy_dma_buf;
+			drv_data->tx_map_len = sizeof(drv_data->dummy_dma_buf);
+			drv_data->tx_dma = dma_map_single(dev,
+							buf,
+							drv_data->tx_map_len,
+							DMA_TO_DEVICE);
+			if (dma_mapping_error(drv_data->tx_dma))
+				return -1;
+
+			drv_data->tx_dma_needs_unmap = 1;
+
+			/* Flags transfer as rd_only for pump_transfers() DMA
+			   regs programming (should be redundant) */
+			drv_data->tx = NULL;
+
+			return 0;
+		}
+	}
+
+	if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx))
+		return -1;
+
+	/* NULL rx means write-only transfer and no map needed
+	   since rx DMA will not be used */
+	if (drv_data->rx) {
+		buf = drv_data->rx;
+		drv_data->rx_dma = dma_map_single(
+					dev,
+					buf,
+					drv_data->len,
+					DMA_FROM_DEVICE);
+		if (dma_mapping_error(drv_data->rx_dma))
+			return -1;
+		drv_data->rx_dma_needs_unmap = 1;
+	}
+
+	if (drv_data->tx == NULL) {
+		/* Read only message --> use drv_data->dummy_dma_buf for dummy
+		   writes to achive reads */
+		buf = &drv_data->dummy_dma_buf;
+		drv_data->tx_map_len = sizeof(drv_data->dummy_dma_buf);
+	} else {
+		buf = drv_data->tx;
+		drv_data->tx_map_len = drv_data->len;
+	}
+	drv_data->tx_dma = dma_map_single(dev,
+					buf,
+					drv_data->tx_map_len,
+					DMA_TO_DEVICE);
+	if (dma_mapping_error(drv_data->tx_dma)) {
+		if (drv_data->rx_dma) {
+			dma_unmap_single(dev,
+					drv_data->rx_dma,
+					drv_data->len,
+					DMA_FROM_DEVICE);
+			drv_data->rx_dma_needs_unmap = 0;
+		}
+		return -1;
+	}
+	drv_data->tx_dma_needs_unmap = 1;
+
+	return 0;
+}
+
+static void unmap_dma_buffers(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	struct device *dev = &msg->spi->dev;
+
+	if (drv_data->rx_dma_needs_unmap) {
+		dma_unmap_single(dev,
+				drv_data->rx_dma,
+				drv_data->len,
+				DMA_FROM_DEVICE);
+		drv_data->rx_dma_needs_unmap = 0;
+	}
+	if (drv_data->tx_dma_needs_unmap) {
+		dma_unmap_single(dev,
+				drv_data->tx_dma,
+				drv_data->tx_map_len,
+				DMA_TO_DEVICE);
+		drv_data->tx_dma_needs_unmap = 0;
+	}
+}
+
+/* Caller already set message->status (dma is already blocked) */
+static void giveback(struct spi_message *message, struct driver_data *drv_data)
+{
+	void __iomem *regs = drv_data->regs;
+
+	/* Bring SPI to sleep; restore_state() and pump_transfer()
+	   will do new setup */
+	writel(0, regs + SPI_INT_STATUS);
+	writel(0, regs + SPI_DMA);
+
+	drv_data->cs_control(SPI_CS_DEASSERT);
+
+	message->state = NULL;
+	if (message->complete)
+		message->complete(message->context);
+
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	queue_work(drv_data->workqueue, &drv_data->work);
+}
+
+static void dma_err_handler(int channel, void *data, int errcode)
+{
+	struct driver_data *drv_data = data;
+	struct spi_message *msg = drv_data->cur_msg;
+
+	dev_dbg(&drv_data->pdev->dev, "dma_err_handler\n");
+
+	/* Disable both rx and tx dma channels */
+	imx_dma_disable(drv_data->rx_channel);
+	imx_dma_disable(drv_data->tx_channel);
+
+	if (flush(drv_data) == 0)
+		dev_err(&drv_data->pdev->dev,
+				"dma_err_handler - flush failed\n");
+
+	unmap_dma_buffers(drv_data);
+
+	msg->state = ERROR_STATE;
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static void dma_tx_handler(int channel, void *data)
+{
+	struct driver_data *drv_data = data;
+
+	dev_dbg(&drv_data->pdev->dev, "dma_tx_handler\n");
+
+	imx_dma_disable(channel);
+
+	/* Now waits for TX FIFO empty */
+	writel(readl(drv_data->regs + SPI_INT_STATUS) | SPI_INTEN_TE,
+			drv_data->regs + SPI_INT_STATUS);
+}
+
+static irqreturn_t dma_transfer(struct driver_data *drv_data)
+{
+	u32 status;
+	struct spi_message *msg = drv_data->cur_msg;
+	void __iomem *regs = drv_data->regs;
+	unsigned long limit;
+
+	status = readl(regs + SPI_INT_STATUS);
+
+	if ((status & SPI_INTEN_RO) && (status & SPI_STATUS_RO)) {
+		writel(status & ~SPI_INTEN, regs + SPI_INT_STATUS);
+
+		imx_dma_disable(drv_data->rx_channel);
+		unmap_dma_buffers(drv_data);
+
+		if (flush(drv_data) == 0)
+			dev_err(&drv_data->pdev->dev,
+				"dma_transfer - flush failed\n");
+
+		dev_warn(&drv_data->pdev->dev,
+				"dma_transfer - fifo overun\n");
+
+		msg->state = ERROR_STATE;
+		tasklet_schedule(&drv_data->pump_transfers);
+
+		return IRQ_HANDLED;
+	}
+
+	if (status & SPI_STATUS_TE) {
+		writel(status & ~SPI_INTEN_TE, regs + SPI_INT_STATUS);
+
+		if (drv_data->rx) {
+			/* Wait end of transfer before read trailing data */
+			limit = loops_per_jiffy << 1;
+			while ((readl(regs + SPI_CONTROL) & SPI_CONTROL_XCH) &&
+					limit--);
+
+			if (limit == 0)
+				dev_err(&drv_data->pdev->dev,
+					"dma_transfer - end of tx failed\n");
+			else
+				dev_dbg(&drv_data->pdev->dev,
+					"dma_transfer - end of tx\n");
+
+			imx_dma_disable(drv_data->rx_channel);
+			unmap_dma_buffers(drv_data);
+
+			/* Calculate number of trailing data and read them */
+			dev_dbg(&drv_data->pdev->dev,
+				"dma_transfer - test = 0x%08X\n",
+				readl(regs + SPI_TEST));
+			drv_data->rx = drv_data->rx_end -
+					((readl(regs + SPI_TEST) &
+					SPI_TEST_RXCNT) >>
+					SPI_TEST_RXCNT_LSB)*drv_data->n_bytes;
+			read(drv_data);
+		} else {
+			/* Write only transfer */
+			unmap_dma_buffers(drv_data);
+
+			if (flush(drv_data) == 0)
+				dev_err(&drv_data->pdev->dev,
+					"dma_transfer - flush failed\n");
+		}
+
+		/* End of transfer, update total byte transfered */
+		msg->actual_length += drv_data->len;
+
+		/* Release chip select if requested, transfer delays are
+		   handled in pump_transfers() */
+		if (drv_data->cs_change)
+			drv_data->cs_control(SPI_CS_DEASSERT);
+
+		/* Move to next transfer */
+		msg->state = next_transfer(drv_data);
+
+		/* Schedule transfer tasklet */
+		tasklet_schedule(&drv_data->pump_transfers);
+
+		return IRQ_HANDLED;
+	}
+
+	/* Opps problem detected */
+	return IRQ_NONE;
+}
+
+static irqreturn_t interrupt_wronly_transfer(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	void __iomem *regs = drv_data->regs;
+	u32 status;
+	irqreturn_t handled = IRQ_NONE;
+
+	status = readl(regs + SPI_INT_STATUS);
+
+	while (status & SPI_STATUS_TH) {
+		dev_dbg(&drv_data->pdev->dev,
+			"interrupt_wronly_transfer - status = 0x%08X\n", status);
+
+		/* Pump data */
+		if (write(drv_data)) {
+			writel(readl(regs + SPI_INT_STATUS) & ~SPI_INTEN,
+				regs + SPI_INT_STATUS);
+
+			dev_dbg(&drv_data->pdev->dev,
+				"interrupt_wronly_transfer - end of tx\n");
+
+			if (flush(drv_data) == 0)
+				dev_err(&drv_data->pdev->dev,
+					"interrupt_wronly_transfer - "
+					"flush failed\n");
+
+			/* End of transfer, update total byte transfered */
+			msg->actual_length += drv_data->len;
+
+			/* Release chip select if requested, transfer delays are
+			   handled in pump_transfers */
+			if (drv_data->cs_change)
+				drv_data->cs_control(SPI_CS_DEASSERT);
+
+			/* Move to next transfer */
+			msg->state = next_transfer(drv_data);
+
+			/* Schedule transfer tasklet */
+			tasklet_schedule(&drv_data->pump_transfers);
+
+			return IRQ_HANDLED;
+		}
+
+		status = readl(regs + SPI_INT_STATUS);
+
+		/* We did something */
+		handled = IRQ_HANDLED;
+	}
+
+	return handled;
+}
+
+static irqreturn_t interrupt_transfer(struct driver_data *drv_data)
+{
+	struct spi_message *msg = drv_data->cur_msg;
+	void __iomem *regs = drv_data->regs;
+	u32 status;
+	irqreturn_t handled = IRQ_NONE;
+	unsigned long limit;
+
+	status = readl(regs + SPI_INT_STATUS);
+
+	while (status & (SPI_STATUS_TH | SPI_STATUS_RO)) {
+		dev_dbg(&drv_data->pdev->dev,
+			"interrupt_transfer - status = 0x%08X\n", status);
+
+		if (status & SPI_STATUS_RO) {
+			writel(readl(regs + SPI_INT_STATUS) & ~SPI_INTEN,
+				regs + SPI_INT_STATUS);
+
+			dev_warn(&drv_data->pdev->dev,
+				"interrupt_transfer - fifo overun\n"
+				"    data not yet written = %d\n"
+				"    data not yet read    = %d\n",
+				data_to_write(drv_data),
+				data_to_read(drv_data));
+
+			if (flush(drv_data) == 0)
+				dev_err(&drv_data->pdev->dev,
+					"interrupt_transfer - flush failed\n");
+
+			msg->state = ERROR_STATE;
+			tasklet_schedule(&drv_data->pump_transfers);
+
+			return IRQ_HANDLED;
+		}
+
+		/* Pump data */
+		read(drv_data);
+		if (write(drv_data)) {
+			writel(readl(regs + SPI_INT_STATUS) & ~SPI_INTEN,
+				regs + SPI_INT_STATUS);
+
+			dev_dbg(&drv_data->pdev->dev,
+				"interrupt_transfer - end of tx\n");
+
+			/* Read trailing bytes */
+			limit = loops_per_jiffy << 1;
+			while ((read(drv_data) == 0) && limit--);
+
+			if (limit == 0)
+				dev_err(&drv_data->pdev->dev,
+					"interrupt_transfer - "
+					"trailing byte read failed\n");
+			else
+				dev_dbg(&drv_data->pdev->dev,
+					"interrupt_transfer - end of rx\n");
+
+			/* End of transfer, update total byte transfered */
+			msg->actual_length += drv_data->len;
+
+			/* Release chip select if requested, transfer delays are
+			   handled in pump_transfers */
+			if (drv_data->cs_change)
+				drv_data->cs_control(SPI_CS_DEASSERT);
+
+			/* Move to next transfer */
+			msg->state = next_transfer(drv_data);
+
+			/* Schedule transfer tasklet */
+			tasklet_schedule(&drv_data->pump_transfers);
+
+			return IRQ_HANDLED;
+		}
+
+		status = readl(regs + SPI_INT_STATUS);
+
+		/* We did something */
+		handled = IRQ_HANDLED;
+	}
+
+	return handled;
+}
+
+static irqreturn_t spi_int(int irq, void *dev_id)
+{
+	struct driver_data *drv_data = (struct driver_data *)dev_id;
+
+	if (!drv_data->cur_msg) {
+		dev_err(&drv_data->pdev->dev,
+			"spi_int - bad message state\n");
+		/* Never fail */
+		return IRQ_HANDLED;
+	}
+
+	return drv_data->transfer_handler(drv_data);
+}
+
+static inline u32 spi_speed_hz(u32 data_rate)
+{
+	return imx_get_perclk2() / (4 << ((data_rate) >> 13));
+}
+
+static u32 spi_data_rate(u32 speed_hz)
+{
+	u32 div;
+	u32 quantized_hz = imx_get_perclk2() >> 2;
+
+	for (div = SPI_PERCLK2_DIV_MIN;
+		div <= SPI_PERCLK2_DIV_MAX;
+		div++, quantized_hz >>= 1) {
+			if (quantized_hz <= speed_hz)
+				/* Max available speed LEQ required speed */
+				return div << 13;
+	}
+	return SPI_CONTROL_DATARATE_BAD;
+}
+
+static void pump_transfers(unsigned long data)
+{
+	struct driver_data *drv_data = (struct driver_data *)data;
+	struct spi_message *message;
+	struct spi_transfer *transfer, *previous;
+	struct chip_data *chip;
+	void __iomem *regs;
+	u32 tmp, control;
+
+	dev_dbg(&drv_data->pdev->dev, "pump_transfer\n");
+
+	message = drv_data->cur_msg;
+
+	/* Handle for abort */
+	if (message->state == ERROR_STATE) {
+		message->status = -EIO;
+		giveback(message, drv_data);
+		return;
+	}
+
+	/* Handle end of message */
+	if (message->state == DONE_STATE) {
+		message->status = 0;
+		giveback(message, drv_data);
+		return;
+	}
+
+	chip = drv_data->cur_chip;
+
+	/* Delay if requested at end of transfer*/
+	transfer = drv_data->cur_transfer;
+	if (message->state == RUNNING_STATE) {
+		previous = list_entry(transfer->transfer_list.prev,
+					struct spi_transfer,
+					transfer_list);
+		if (previous->delay_usecs)
+			udelay(previous->delay_usecs);
+	} else {
+		/* START_STATE */
+		message->state = RUNNING_STATE;
+		drv_data->cs_control = chip->cs_control;
+	}
+
+	transfer = drv_data->cur_transfer;
+	drv_data->tx = (void *)transfer->tx_buf;
+	drv_data->tx_end = drv_data->tx + transfer->len;
+	drv_data->rx = transfer->rx_buf;
+	drv_data->rx_end = drv_data->rx + transfer->len;
+	drv_data->rx_dma = transfer->rx_dma;
+	drv_data->tx_dma = transfer->tx_dma;
+	drv_data->len = transfer->len;
+	drv_data->cs_change = transfer->cs_change;
+	drv_data->rd_only = (drv_data->tx == NULL);
+
+	regs = drv_data->regs;
+	control = readl(regs + SPI_CONTROL);
+
+	/* Bits per word setup */
+	tmp = transfer->bits_per_word;
+	if (tmp == 0) {
+		/* Use device setup */
+		tmp = chip->bits_per_word;
+		drv_data->n_bytes = chip->n_bytes;
+	} else
+		/* Use per-transfer setup */
+		drv_data->n_bytes = (tmp <= 8) ? 1 : 2;
+	u32_EDIT(control, SPI_CONTROL_BITCOUNT_MASK, tmp - 1);
+
+	/* Speed setup (surely valid because already checked) */
+	tmp = transfer->speed_hz;
+	if (tmp == 0)
+		tmp = chip->max_speed_hz;
+	tmp = spi_data_rate(tmp);
+	u32_EDIT(control, SPI_CONTROL_DATARATE, tmp);
+
+	writel(control, regs + SPI_CONTROL);
+
+	/* Assert device chip-select */
+	drv_data->cs_control(SPI_CS_ASSERT);
+
+	/* DMA cannot read/write SPI FIFOs other than 16 bits at a time; hence
+	   if bits_per_word is less or equal 8 PIO transfers are performed.
+	   Moreover DMA is convinient for transfer length bigger than FIFOs
+	   byte size. */
+	if ((drv_data->n_bytes == 2) &&
+		(drv_data->len > SPI_FIFO_DEPTH*SPI_FIFO_BYTE_WIDTH) &&
+		(map_dma_buffers(drv_data) == 0)) {
+		dev_dbg(&drv_data->pdev->dev,
+			"pump dma transfer\n"
+			"    tx      = %p\n"
+			"    tx_dma  = %08X\n"
+			"    rx      = %p\n"
+			"    rx_dma  = %08X\n"
+			"    len     = %d\n",
+			drv_data->tx,
+			(unsigned int)drv_data->tx_dma,
+			drv_data->rx,
+			(unsigned int)drv_data->rx_dma,
+			drv_data->len);
+
+		/* Ensure we have the correct interrupt handler */
+		drv_data->transfer_handler = dma_transfer;
+
+		/* Trigger transfer */
+		writel(readl(regs + SPI_CONTROL) | SPI_CONTROL_XCH,
+			regs + SPI_CONTROL);
+
+		/* Setup tx DMA */
+		if (drv_data->tx)
+			/* Linear source address */
+			CCR(drv_data->tx_channel) =
+				CCR_DMOD_FIFO |
+				CCR_SMOD_LINEAR |
+				CCR_SSIZ_32 | CCR_DSIZ_16 |
+				CCR_REN;
+		else
+			/* Read only transfer -> fixed source address for
+			   dummy write to achive read */
+			CCR(drv_data->tx_channel) =
+				CCR_DMOD_FIFO |
+				CCR_SMOD_FIFO |
+				CCR_SSIZ_32 | CCR_DSIZ_16 |
+				CCR_REN;
+
+		imx_dma_setup_single(
+			drv_data->tx_channel,
+			drv_data->tx_dma,
+			drv_data->len,
+			drv_data->rd_data_phys + 4,
+			DMA_MODE_WRITE);
+
+		if (drv_data->rx) {
+			/* Setup rx DMA for linear destination address */
+			CCR(drv_data->rx_channel) =
+				CCR_DMOD_LINEAR |
+				CCR_SMOD_FIFO |
+				CCR_DSIZ_32 | CCR_SSIZ_16 |
+				CCR_REN;
+			imx_dma_setup_single(
+				drv_data->rx_channel,
+				drv_data->rx_dma,
+				drv_data->len,
+				drv_data->rd_data_phys,
+				DMA_MODE_READ);
+			imx_dma_enable(drv_data->rx_channel);
+
+			/* Enable SPI interrupt */
+			writel(SPI_INTEN_RO, regs + SPI_INT_STATUS);
+
+			/* Set SPI to request DMA service on both
+			   Rx and Tx half fifo watermark */
+			writel(SPI_DMA_RHDEN | SPI_DMA_THDEN, regs + SPI_DMA);
+		} else
+			/* Write only access -> set SPI to request DMA
+			   service on Tx half fifo watermark */
+			writel(SPI_DMA_THDEN, regs + SPI_DMA);
+
+		imx_dma_enable(drv_data->tx_channel);
+	} else {
+		dev_dbg(&drv_data->pdev->dev,
+			"pump pio transfer\n"
+			"    tx      = %p\n"
+			"    rx      = %p\n"
+			"    len     = %d\n",
+			drv_data->tx,
+			drv_data->rx,
+			drv_data->len);
+
+		/* Ensure we have the correct interrupt handler	*/
+		if (drv_data->rx)
+			drv_data->transfer_handler = interrupt_transfer;
+		else
+			drv_data->transfer_handler = interrupt_wronly_transfer;
+
+		/* Enable SPI interrupt */
+		if (drv_data->rx)
+			writel(SPI_INTEN_TH | SPI_INTEN_RO,
+				regs + SPI_INT_STATUS);
+		else
+			writel(SPI_INTEN_TH, regs + SPI_INT_STATUS);
+	}
+}
+
+static void pump_messages(struct work_struct *work)
+{
+	struct driver_data *drv_data =
+				container_of(work, struct driver_data, work);
+	unsigned long flags;
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) {
+		drv_data->busy = 0;
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Make sure we are not already running a message */
+	if (drv_data->cur_msg) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return;
+	}
+
+	/* Extract head of queue */
+	drv_data->cur_msg = list_entry(drv_data->queue.next,
+					struct spi_message, queue);
+	list_del_init(&drv_data->cur_msg->queue);
+	drv_data->busy = 1;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	/* Initial message state */
+	drv_data->cur_msg->state = START_STATE;
+	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
+						struct spi_transfer,
+						transfer_list);
+
+	/* Setup the SPI using the per chip configuration */
+	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
+	restore_state(drv_data);
+
+	/* Mark as busy and launch transfers */
+	tasklet_schedule(&drv_data->pump_transfers);
+}
+
+static int transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	u32 min_speed_hz, max_speed_hz, tmp;
+	struct spi_transfer *trans;
+	unsigned long flags;
+
+	msg->actual_length = 0;
+
+	/* Per transfer setup check */
+	min_speed_hz = spi_speed_hz(SPI_CONTROL_DATARATE_MIN);
+	max_speed_hz = spi->max_speed_hz;
+	list_for_each_entry(trans, &msg->transfers, transfer_list) {
+		tmp = trans->bits_per_word;
+		if (tmp > 16) {
+			dev_err(&drv_data->pdev->dev,
+				"message rejected : "
+				"invalid transfer bits_per_word (%d bits)\n",
+				tmp);
+			goto msg_rejected;
+		}
+		tmp = trans->speed_hz;
+		if (tmp) {
+			if (tmp < min_speed_hz) {
+				dev_err(&drv_data->pdev->dev,
+					"message rejected : "
+					"device min speed (%d Hz) exceeds "
+					"required transfer speed (%d Hz)\n",
+					min_speed_hz,
+					tmp);
+				goto msg_rejected;
+			} else if (tmp > max_speed_hz) {
+				dev_err(&drv_data->pdev->dev,
+					"message rejected : "
+					"transfer speed (%d Hz) exceeds "
+					"device max speed (%d Hz)\n",
+					tmp,
+					max_speed_hz);
+				goto msg_rejected;
+			}
+		}
+	}
+
+	/* Message accepted */
+	msg->status = -EINPROGRESS;
+	msg->state = START_STATE;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (drv_data->run == QUEUE_STOPPED) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	list_add_tail(&msg->queue, &drv_data->queue);
+	if (drv_data->run == QUEUE_RUNNING && !drv_data->busy)
+		queue_work(drv_data->workqueue, &drv_data->work);
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+	return 0;
+
+msg_rejected:
+	/* Message rejected and not queued */
+	msg->status = -EINVAL;
+	msg->state = ERROR_STATE;
+	if (msg->complete)
+		msg->complete(msg->context);
+	return -EINVAL;
+}
+
+/* On first setup bad values must free chip_data memory since will cause
+   spi_new_device to fail. Bad value setup from protocol driver are simply not
+   applied and notified to the calling driver. */
+static int setup(struct spi_device *spi)
+{
+	struct spi_imx_chip *chip_info;
+	struct chip_data *chip;
+	int first_setup = 0;
+	u32 tmp;
+	int status = 0;
+
+	/* Get controller data */
+	chip_info = spi->controller_data;
+
+	/* Get controller_state */
+	chip = spi_get_ctldata(spi);
+	if (chip == NULL) {
+		first_setup = 1;
+
+		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+		if (!chip) {
+			dev_err(&spi->dev,
+				"setup - cannot allocate controller state");
+			return -ENOMEM;
+		}
+		chip->control = SPI_DEFAULT_CONTROL;
+
+		if (chip_info == NULL) {
+			/* spi_board_info.controller_data not is supplied */
+			chip_info = kzalloc(sizeof(struct spi_imx_chip),
+						GFP_KERNEL);
+			if (!chip_info) {
+				dev_err(&spi->dev,
+					"setup - "
+					"cannot allocate controller data");
+				status = -ENOMEM;
+				goto err_first_setup;
+			}
+			/* Set controller data default value */
+			chip_info->enable_loopback =
+						SPI_DEFAULT_ENABLE_LOOPBACK;
+			chip_info->enable_dma = SPI_DEFAULT_ENABLE_DMA;
+			chip_info->ins_ss_pulse = 1;
+			chip_info->bclk_wait = SPI_DEFAULT_PERIOD_WAIT;
+			chip_info->cs_control = null_cs_control;
+		}
+	}
+
+	/* Now set controller state based on controller data */
+
+	if (first_setup) {
+		/* SPI loopback */
+		if (chip_info->enable_loopback)
+			chip->test = SPI_TEST_LBC;
+		else
+			chip->test = 0;
+
+		/* SPI dma driven */
+		chip->enable_dma = chip_info->enable_dma;
+
+		/* SPI /SS pulse between spi burst */
+		if (chip_info->ins_ss_pulse)
+			u32_EDIT(chip->control,
+				SPI_CONTROL_SSCTL, SPI_CONTROL_SSCTL_1);
+		else
+			u32_EDIT(chip->control,
+				SPI_CONTROL_SSCTL, SPI_CONTROL_SSCTL_0);
+
+		/* SPI bclk waits between each bits_per_word spi burst */
+		if (chip_info->bclk_wait > SPI_PERIOD_MAX_WAIT) {
+			dev_err(&spi->dev,
+				"setup - "
+				"bclk_wait exceeds max allowed (%d)\n",
+				SPI_PERIOD_MAX_WAIT);
+			goto err_first_setup;
+		}
+		chip->period = SPI_PERIOD_CSRC_BCLK |
+				(chip_info->bclk_wait & SPI_PERIOD_WAIT);
+	}
+
+	/* SPI mode */
+	tmp = spi->mode;
+	if (tmp & SPI_LSB_FIRST) {
+		status = -EINVAL;
+		if (first_setup) {
+			dev_err(&spi->dev,
+				"setup - "
+				"HW doesn't support LSB first transfer\n");
+			goto err_first_setup;
+		} else {
+			dev_err(&spi->dev,
+				"setup - "
+				"HW doesn't support LSB first transfer, "
+				"default to MSB first\n");
+			spi->mode &= ~SPI_LSB_FIRST;
+		}
+	}
+	if (tmp & SPI_CS_HIGH) {
+		u32_EDIT(chip->control,
+				SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH);
+	}
+	switch (tmp & SPI_MODE_3) {
+	case SPI_MODE_0:
+		tmp = 0;
+		break;
+	case SPI_MODE_1:
+		tmp = SPI_CONTROL_PHA_1;
+		break;
+	case SPI_MODE_2:
+		tmp = SPI_CONTROL_POL_ACT_LOW;
+		break;
+	default:
+		/* SPI_MODE_3 */
+		tmp = SPI_CONTROL_PHA_1 | SPI_CONTROL_POL_ACT_LOW;
+		break;
+	}
+	u32_EDIT(chip->control, SPI_CONTROL_POL | SPI_CONTROL_PHA, tmp);
+
+	/* SPI word width */
+	tmp = spi->bits_per_word;
+	if (tmp == 0) {
+		tmp = 8;
+		spi->bits_per_word = 8;
+	} else if (tmp > 16) {
+		status = -EINVAL;
+		dev_err(&spi->dev,
+			"setup - "
+			"invalid bits_per_word (%d)\n",
+			tmp);
+		if (first_setup)
+			goto err_first_setup;
+		else {
+			/* Undo setup using chip as backup copy */
+			tmp = chip->bits_per_word;
+			spi->bits_per_word = tmp;
+		}
+	}
+	chip->bits_per_word = tmp;
+	u32_EDIT(chip->control, SPI_CONTROL_BITCOUNT_MASK, tmp - 1);
+	chip->n_bytes = (tmp <= 8) ? 1 : 2;
+
+	/* SPI datarate */
+	tmp = spi_data_rate(spi->max_speed_hz);
+	if (tmp == SPI_CONTROL_DATARATE_BAD) {
+		status = -EINVAL;
+		dev_err(&spi->dev,
+			"setup - "
+			"HW min speed (%d Hz) exceeds required "
+			"max speed (%d Hz)\n",
+			spi_speed_hz(SPI_CONTROL_DATARATE_MIN),
+			spi->max_speed_hz);
+		if (first_setup)
+			goto err_first_setup;
+		else
+			/* Undo setup using chip as backup copy */
+			spi->max_speed_hz = chip->max_speed_hz;
+	} else {
+		u32_EDIT(chip->control, SPI_CONTROL_DATARATE, tmp);
+		/* Actual rounded max_speed_hz */
+		tmp = spi_speed_hz(tmp);
+		spi->max_speed_hz = tmp;
+		chip->max_speed_hz = tmp;
+	}
+
+	/* SPI chip-select management */
+	if (chip_info->cs_control)
+		chip->cs_control = chip_info->cs_control;
+	else
+		chip->cs_control = null_cs_control;
+
+	/* Save controller_state */
+	spi_set_ctldata(spi, chip);
+
+	/* Summary */
+	dev_dbg(&spi->dev,
+		"setup succeded\n"
+		"    loopback enable   = %s\n"
+		"    dma enable        = %s\n"
+		"    insert /ss pulse  = %s\n"
+		"    period wait       = %d\n"
+		"    mode              = %d\n"
+		"    bits per word     = %d\n"
+		"    min speed         = %d Hz\n"
+		"    rounded max speed = %d Hz\n",
+		chip->test & SPI_TEST_LBC ? "Yes" : "No",
+		chip->enable_dma ? "Yes" : "No",
+		chip->control & SPI_CONTROL_SSCTL ? "Yes" : "No",
+		chip->period & SPI_PERIOD_WAIT,
+		spi->mode,
+		spi->bits_per_word,
+		spi_speed_hz(SPI_CONTROL_DATARATE_MIN),
+		spi->max_speed_hz);
+
+err_first_setup:
+	kfree(chip);
+	return status;
+}
+
+static void cleanup(const struct spi_device *spi)
+{
+	struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
+	kfree(chip);
+}
+
+static int init_queue(struct driver_data *drv_data)
+{
+	INIT_LIST_HEAD(&drv_data->queue);
+	spin_lock_init(&drv_data->lock);
+
+	drv_data->run = QUEUE_STOPPED;
+	drv_data->busy = 0;
+
+	tasklet_init(&drv_data->pump_transfers,
+			pump_transfers,	(unsigned long)drv_data);
+
+	INIT_WORK(&drv_data->work, pump_messages);
+	drv_data->workqueue = create_singlethread_workqueue(
+					drv_data->master->cdev.dev->bus_id);
+	if (drv_data->workqueue == NULL)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int start_queue(struct driver_data *drv_data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	if (drv_data->run == QUEUE_RUNNING || drv_data->busy) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -EBUSY;
+	}
+
+	drv_data->run = QUEUE_RUNNING;
+	drv_data->cur_msg = NULL;
+	drv_data->cur_transfer = NULL;
+	drv_data->cur_chip = NULL;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	queue_work(drv_data->workqueue, &drv_data->work);
+
+	return 0;
+}
+
+static int stop_queue(struct driver_data *drv_data)
+{
+	unsigned long flags;
+	unsigned limit = 500;
+	int status = 0;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+
+	/* This is a bit lame, but is optimized for the common execution path.
+	 * A wait_queue on the drv_data->busy could be used, but then the common
+	 * execution path (pump_messages) would be required to call wake_up or
+	 * friends on every SPI message. Do this instead */
+	drv_data->run = QUEUE_STOPPED;
+	while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&drv_data->lock, flags);
+	}
+
+	if (!list_empty(&drv_data->queue) || drv_data->busy)
+		status = -EBUSY;
+
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return status;
+}
+
+static int destroy_queue(struct driver_data *drv_data)
+{
+	int status;
+
+	status = stop_queue(drv_data);
+	if (status != 0)
+		return status;
+
+	if (drv_data->workqueue)
+		destroy_workqueue(drv_data->workqueue);
+
+	return 0;
+}
+
+static int spi_imx_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct spi_imx_master *platform_info;
+	struct spi_master *master;
+	struct driver_data *drv_data = NULL;
+	struct resource *res;
+	int irq, status = 0;
+
+	platform_info = dev->platform_data;
+	if (platform_info == NULL) {
+		dev_err(&pdev->dev, "probe - no platform data supplied\n");
+		status = -ENODEV;
+		goto err_no_pdata;
+	}
+
+	/* Allocate master with space for drv_data */
+	master = spi_alloc_master(dev, sizeof(struct driver_data));
+	if (!master) {
+		dev_err(&pdev->dev, "probe - cannot alloc spi_master\n");
+		status = -ENOMEM;
+		goto err_no_mem;
+	}
+	drv_data = spi_master_get_devdata(master);
+	drv_data->master = master;
+	drv_data->master_info = platform_info;
+	drv_data->pdev = pdev;
+
+	master->bus_num = pdev->id;
+	master->num_chipselect = platform_info->num_chipselect;
+	master->cleanup = cleanup;
+	master->setup = setup;
+	master->transfer = transfer;
+
+	drv_data->dummy_dma_buf = SPI_DUMMY_u32;
+
+	/* Find and map resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "probe - MEM resources not defined\n");
+		status = -ENODEV;
+		goto err_no_iores;
+	}
+	drv_data->ioarea = request_mem_region(res->start,
+						res->end - res->start + 1,
+						pdev->name);
+	if (drv_data->ioarea == NULL) {
+		dev_err(&pdev->dev, "probe - cannot reserve region\n");
+		status = -ENXIO;
+		goto err_no_iores;
+	}
+	drv_data->regs = ioremap(res->start, res->end - res->start + 1);
+	if (drv_data->regs == NULL) {
+		dev_err(&pdev->dev, "probe - cannot map IO\n");
+		status = -ENXIO;
+		goto err_no_iomap;
+	}
+	drv_data->rd_data_phys = (dma_addr_t)res->start;
+
+	/* Attach to IRQ */
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "probe - IRQ resource not defined\n");
+		status = -ENODEV;
+		goto err_no_irqres;
+	}
+	status = request_irq(irq, spi_int, IRQF_DISABLED, dev->bus_id, drv_data);
+	if (status < 0) {
+		dev_err(&pdev->dev, "probe - cannot get IRQ (%d)\n", status);
+		goto err_no_irqres;
+	}
+
+	/* Setup DMA if requested */
+	drv_data->tx_channel = -1;
+	drv_data->rx_channel = -1;
+	if (platform_info->enable_dma) {
+		/* Get rx DMA channel */
+		status = imx_dma_request_by_prio(&drv_data->rx_channel,
+			"spi_imx_rx", DMA_PRIO_HIGH);
+		if (status < 0) {
+			dev_err(dev,
+				"probe - problem (%d) requesting rx channel\n",
+				status);
+			goto err_no_rxdma;
+		} else
+			imx_dma_setup_handlers(drv_data->rx_channel, NULL,
+						dma_err_handler, drv_data);
+
+		/* Get tx DMA channel */
+		status = imx_dma_request_by_prio(&drv_data->tx_channel,
+						"spi_imx_tx", DMA_PRIO_MEDIUM);
+		if (status < 0) {
+			dev_err(dev,
+				"probe - problem (%d) requesting tx channel\n",
+				status);
+			imx_dma_free(drv_data->rx_channel);
+			goto err_no_txdma;
+		} else
+			imx_dma_setup_handlers(drv_data->tx_channel,
+						dma_tx_handler, dma_err_handler,
+						drv_data);
+
+		/* Set request source and burst length for allocated channels */
+		switch (drv_data->pdev->id) {
+		case 1:
+			/* Using SPI1 */
+			RSSR(drv_data->rx_channel) = DMA_REQ_SPI1_R;
+			RSSR(drv_data->tx_channel) = DMA_REQ_SPI1_T;
+			break;
+		case 2:
+			/* Using SPI2 */
+			RSSR(drv_data->rx_channel) = DMA_REQ_SPI2_R;
+			RSSR(drv_data->tx_channel) = DMA_REQ_SPI2_T;
+			break;
+		default:
+			dev_err(dev, "probe - bad SPI Id\n");
+			imx_dma_free(drv_data->rx_channel);
+			imx_dma_free(drv_data->tx_channel);
+			status = -ENODEV;
+			goto err_no_devid;
+		}
+		BLR(drv_data->rx_channel) = SPI_DMA_BLR;
+		BLR(drv_data->tx_channel) = SPI_DMA_BLR;
+	}
+
+	/* Load default SPI configuration */
+	writel(SPI_RESET_START, drv_data->regs + SPI_RESET);
+	writel(0, drv_data->regs + SPI_RESET);
+	writel(SPI_DEFAULT_CONTROL, drv_data->regs + SPI_CONTROL);
+
+	/* Initial and start queue */
+	status = init_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "probe - problem initializing queue\n");
+		goto err_init_queue;
+	}
+	status = start_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "probe - problem starting queue\n");
+		goto err_start_queue;
+	}
+
+	/* Register with the SPI framework */
+	platform_set_drvdata(pdev, drv_data);
+	status = spi_register_master(master);
+	if (status != 0) {
+		dev_err(&pdev->dev, "probe - problem registering spi master\n");
+		goto err_spi_register;
+	}
+
+	dev_dbg(dev, "probe succeded\n");
+	return 0;
+
+err_init_queue:
+err_start_queue:
+err_spi_register:
+	destroy_queue(drv_data);
+
+err_no_rxdma:
+err_no_txdma:
+err_no_devid:
+	free_irq(irq, drv_data);
+
+err_no_irqres:
+	iounmap(drv_data->regs);
+
+err_no_iomap:
+	release_resource(drv_data->ioarea);
+	kfree(drv_data->ioarea);
+
+err_no_iores:
+	spi_master_put(master);
+
+err_no_pdata:
+err_no_mem:
+	return status;
+}
+
+static int __devexit spi_imx_remove(struct platform_device *pdev)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	int irq;
+	int status = 0;
+
+	if (!drv_data)
+		return 0;
+
+	tasklet_kill(&drv_data->pump_transfers);
+
+	/* Remove the queue */
+	status = destroy_queue(drv_data);
+	if (status != 0) {
+		dev_err(&pdev->dev, "queue remove failed (%d)\n", status);
+		return status;
+	}
+
+	/* Reset SPI */
+	writel(SPI_RESET_START, drv_data->regs + SPI_RESET);
+	writel(0, drv_data->regs + SPI_RESET);
+
+	/* Release DMA */
+	if (drv_data->master_info->enable_dma) {
+		RSSR(drv_data->rx_channel) = 0;
+		RSSR(drv_data->tx_channel) = 0;
+		imx_dma_free(drv_data->tx_channel);
+		imx_dma_free(drv_data->rx_channel);
+	}
+
+	/* Release IRQ */
+	irq = platform_get_irq(pdev, 0);
+	if (irq >= 0)
+		free_irq(irq, drv_data);
+
+	/* Release map resources */
+	iounmap(drv_data->regs);
+	release_resource(drv_data->ioarea);
+	kfree(drv_data->ioarea);
+
+	/* Disconnect from the SPI framework */
+	spi_unregister_master(drv_data->master);
+	spi_master_put(drv_data->master);
+
+	/* Prevent double remove */
+	platform_set_drvdata(pdev, NULL);
+
+	dev_dbg(&pdev->dev, "remove succeded\n");
+
+	return 0;
+}
+
+static void spi_imx_shutdown(struct platform_device *pdev)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+
+	/* Reset SPI */
+	writel(SPI_RESET_START, drv_data->regs + SPI_RESET);
+	writel(0, drv_data->regs + SPI_RESET);
+
+	dev_dbg(&pdev->dev, "shutdown succeded\n");
+}
+
+#ifdef CONFIG_PM
+static int suspend_devices(struct device *dev, void *pm_message)
+{
+	pm_message_t *state = pm_message;
+
+	if (dev->power.power_state.event != state->event) {
+		dev_warn(dev, "pm state does not match request\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int spi_imx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	status = stop_queue(drv_data);
+	if (status != 0) {
+		dev_warn(&pdev->dev, "suspend cannot stop queue\n");
+		return status;
+	}
+
+	dev_dbg(&pdev->dev, "suspended\n");
+
+	return 0;
+}
+
+static int spi_imx_resume(struct platform_device *pdev)
+{
+	struct driver_data *drv_data = platform_get_drvdata(pdev);
+	int status = 0;
+
+	/* Start the queue running */
+	status = start_queue(drv_data);
+	if (status != 0)
+		dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
+	else
+		dev_dbg(&pdev->dev, "resumed\n");
+
+	return status;
+}
+#else
+#define spi_imx_suspend NULL
+#define spi_imx_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver driver = {
+	.driver = {
+		.name = "imx-spi",
+		.bus = &platform_bus_type,
+		.owner = THIS_MODULE,
+	},
+	.probe = spi_imx_probe,
+	.remove = __devexit_p(spi_imx_remove),
+	.shutdown = spi_imx_shutdown,
+	.suspend = spi_imx_suspend,
+	.resume = spi_imx_resume,
+};
+
+static int __init spi_imx_init(void)
+{
+	return platform_driver_register(&driver);
+}
+module_init(spi_imx_init);
+
+static void __exit spi_imx_exit(void)
+{
+	platform_driver_unregister(&driver);
+}
+module_exit(spi_imx_exit);
+
+MODULE_AUTHOR("Andrea Paterniani, <a.paterniani@swapp-eng.it>");
+MODULE_DESCRIPTION("iMX SPI Contoller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index df4cc1f..71cb64e 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -648,9 +648,9 @@
 	return j->pld_slicr.bits.state;
 }
 
-static BOOL SLIC_SetState(BYTE byState, IXJ *j)
+static bool SLIC_SetState(BYTE byState, IXJ *j)
 {
-	BOOL fRetVal = FALSE;
+	bool fRetVal = false;
 
 	if (j->cardtype == QTI_PHONECARD) {
 		if (j->flags.pcmciasct) {
@@ -659,14 +659,14 @@
 			case PLD_SLIC_STATE_OC:
 				j->pslic.bits.powerdown = 1;
 				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;
-				fRetVal = TRUE;
+				fRetVal = true;
 				break;
 			case PLD_SLIC_STATE_RINGING:
 				if (j->readers || j->writers) {
 					j->pslic.bits.powerdown = 0;
 					j->pslic.bits.ring0 = 1;
 					j->pslic.bits.ring1 = 0;
-					fRetVal = TRUE;
+					fRetVal = true;
 				}
 				break;
 			case PLD_SLIC_STATE_OHT:	/* On-hook transmit */
@@ -679,14 +679,14 @@
 					j->pslic.bits.powerdown = 1;
 				}
 				j->pslic.bits.ring0 = j->pslic.bits.ring1 = 0;
-				fRetVal = TRUE;
+				fRetVal = true;
 				break;
 			case PLD_SLIC_STATE_APR:	/* Active polarity reversal */
 
 			case PLD_SLIC_STATE_OHTPR:	/* OHT polarity reversal */
 
 			default:
-				fRetVal = FALSE;
+				fRetVal = false;
 				break;
 			}
 			j->psccr.bits.dev = 3;
@@ -703,7 +703,7 @@
 			j->pld_slicw.bits.c3 = 0;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_RINGING:
 			j->pld_slicw.bits.c1 = 1;
@@ -711,7 +711,7 @@
 			j->pld_slicw.bits.c3 = 0;
 			j->pld_slicw.bits.b2en = 1;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_ACTIVE:
 			j->pld_slicw.bits.c1 = 0;
@@ -719,7 +719,7 @@
 			j->pld_slicw.bits.c3 = 0;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_OHT:	/* On-hook transmit */
 
@@ -728,7 +728,7 @@
 			j->pld_slicw.bits.c3 = 0;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_TIPOPEN:
 			j->pld_slicw.bits.c1 = 0;
@@ -736,7 +736,7 @@
 			j->pld_slicw.bits.c3 = 1;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_STANDBY:
 			j->pld_slicw.bits.c1 = 1;
@@ -744,7 +744,7 @@
 			j->pld_slicw.bits.c3 = 1;
 			j->pld_slicw.bits.b2en = 1;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_APR:	/* Active polarity reversal */
 
@@ -753,7 +753,7 @@
 			j->pld_slicw.bits.c3 = 1;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		case PLD_SLIC_STATE_OHTPR:	/* OHT polarity reversal */
 
@@ -762,10 +762,10 @@
 			j->pld_slicw.bits.c3 = 1;
 			j->pld_slicw.bits.b2en = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			fRetVal = TRUE;
+			fRetVal = true;
 			break;
 		default:
-			fRetVal = FALSE;
+			fRetVal = false;
 			break;
 		}
 	}
@@ -4969,7 +4969,8 @@
 {
 	int i;
 	BYTES bytes;
-	char CID[ALISDAA_CALLERID_SIZE], mContinue;
+	char CID[ALISDAA_CALLERID_SIZE];
+	bool mContinue;
 	char *pIn, *pOut;
 
 	if (!SCI_Prepare(j))
@@ -5013,7 +5014,7 @@
 
 	pIn = CID;
 	pOut = j->m_DAAShadowRegs.CAO_REGS.CAO.CallerID;
-	mContinue = 1;
+	mContinue = true;
 	while (mContinue) {
 		if ((pIn[1] & 0x03) == 0x01) {
 			pOut[0] = pIn[0];
@@ -5027,7 +5028,7 @@
 		if ((pIn[4] & 0xc0) == 0x40) {
 			pOut[3] = ((pIn[4] & 0x3f) << 2) | ((pIn[3] & 0xc0) >> 6);
 		} else {
-			mContinue = FALSE;
+			mContinue = false;
 		}
 		pIn += 5, pOut += 4;
 	}
@@ -6662,7 +6663,7 @@
 	return fasync_helper(fd, file_p, mode, &j->async_queue);
 }
 
-static struct file_operations ixj_fops =
+static const struct file_operations ixj_fops =
 {
         .owner          = THIS_MODULE,
         .read           = ixj_enhanced_read,
@@ -7498,7 +7499,7 @@
 	return ((inb(wEEPROMAddress) >> 3) & 1);
 }
 
-static BOOL PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult)
+static bool PCIEE_ReadWord(WORD wAddress, WORD wLoc, WORD * pwResult)
 {
 	BYTE lastLCC;
 	WORD wEEPROMAddress = wAddress + 3;
diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h
index 8d69bcd..4c32a43 100644
--- a/drivers/telephony/ixj.h
+++ b/drivers/telephony/ixj.h
@@ -48,15 +48,11 @@
 typedef __u16 WORD;
 typedef __u32 DWORD;
 typedef __u8 BYTE;
-typedef __u8 BOOL;
 
 #ifndef IXJMAX
 #define IXJMAX 16
 #endif
 
-#define TRUE 1
-#define FALSE 0
-
 /******************************************************************************
 *
 *  This structure when unioned with the structures below makes simple byte
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c
index e41f49a..4d8c2a5 100644
--- a/drivers/telephony/phonedev.c
+++ b/drivers/telephony/phonedev.c
@@ -127,7 +127,7 @@
 }
 
 
-static struct file_operations phone_fops =
+static const struct file_operations phone_fops =
 {
 	.owner		= THIS_MODULE,
 	.open		= phone_open,
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index af2934e..75bfab9 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -644,7 +644,7 @@
 }
 
 /* file operations needed when we register this driver */
-static struct file_operations adu_fops = {
+static const struct file_operations adu_fops = {
 	.owner = THIS_MODULE,
 	.read  = adu_read,
 	.write = adu_write,
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index a7932a7..32f0e3a 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -281,8 +281,8 @@
 	/* Register backlight device */
 	snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
 		atomic_inc_return(&count_displays) - 1);
-	pdata->bd = backlight_device_register(bl_name, NULL, NULL,
-						&appledisplay_bl_data);
+	pdata->bd = backlight_device_register(bl_name, NULL,
+		pdata, &appledisplay_bl_data);
 	if (IS_ERR(pdata->bd)) {
 		err("appledisplay: Backlight registration failed");
 		goto error;
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 41c0161..0c1d66d 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -1209,7 +1209,7 @@
 	return retval;
 }
 
-static struct file_operations ftdi_elan_fops = {
+static const struct file_operations ftdi_elan_fops = {
         .owner = THIS_MODULE,
         .llseek = no_llseek,
         .ioctl = ftdi_elan_ioctl,
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 45fe65d..8874cf2 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -85,6 +85,14 @@
 	  blitting. This is used by drivers that don't provide their own
 	  (accelerated) version.
 
+config FB_SVGALIB
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Common utility functions useful to fbdev drivers of VGA-based
+	  cards.
+
 config FB_MACMODES
        tristate
        depends on FB
@@ -346,42 +354,6 @@
 	  and CD32. If you intend to run Linux on any of these systems, say Y;
 	  otherwise say N.
 
-config FB_CYBER
-	tristate "Amiga CyberVision 64 support"
-	depends on FB && ZORRO && BROKEN
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This enables support for the Cybervision 64 graphics card from
-	  Phase5. Please note that its use is not all that intuitive (i.e. if
-	  you have any questions, be sure to ask!). Say N unless you have a
-	  Cybervision 64 or plan to get one before you next recompile the
-	  kernel. Please note that this driver DOES NOT support the
-	  Cybervision 64/3D card, as they use incompatible video chips.
-
-config FB_VIRGE
-	bool "Amiga CyberVision 64/3D support "
-	depends on (FB = y) && ZORRO && BROKEN
-	select FB_CFB_FILLRECT
-	select FB_CFB_COPYAREA
-	select FB_CFB_IMAGEBLIT
-	help
-	  This enables support for the Cybervision 64/3D graphics card from
-	  Phase5. Please note that its use is not all that intuitive (i.e. if
-	  you have any questions, be sure to ask!). Say N unless you have a
-	  Cybervision 64/3D or plan to get one before you next recompile the
-	  kernel. Please note that this driver DOES NOT support the older
-	  Cybervision 64 card, as they use incompatible video chips.
-
-config FB_RETINAZ3
-	tristate "Amiga Retina Z3 support"
-	depends on (FB = y) && ZORRO && BROKEN
-	help
-	  This enables support for the Retina Z3 graphics card. Say N unless
-	  you have a Retina Z3 or plan to get one before you next recompile
-	  the kernel.
-
 config FB_FM2
 	bool "Amiga FrameMaster II/Rainbow II support"
 	depends on (FB = y) && ZORRO
@@ -617,10 +589,6 @@
 	  This is the amount of memory reserved for the framebuffer,
 	  which can be any value between 1MB and 8MB.
 
-config FB_SUN3
-	bool "Sun3 framebuffer support"
-	depends on (FB = y) && (SUN3 || SUN3X) && BROKEN
-
 config FB_SBUS
 	bool "SBUS and UPA framebuffers"
 	depends on (FB = y) && SPARC
@@ -629,7 +597,7 @@
 
 config FB_BW2
 	bool "BWtwo support"
-	depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && (SPARC && FB_SBUS)
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -638,7 +606,7 @@
 
 config FB_CG3
 	bool "CGthree support"
-	depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && (SPARC && FB_SBUS)
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -647,7 +615,7 @@
 
 config FB_CG6
 	bool "CGsix (GX,TurboGX) support"
-	depends on (FB = y) && (SPARC && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && (SPARC && FB_SBUS)
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
 	help
@@ -1141,11 +1109,16 @@
 	help
 	  Say Y here if you want to control the backlight of your display.
 
-config FB_S3TRIO
-	bool "S3 Trio display support"
-	depends on (FB = y) && PPC && BROKEN
-	help
-	  If you have a S3 Trio say Y. Say N for S3 Virge.
+config FB_S3
+	tristate "S3 Trio/Virge support"
+	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_TILEBLITTING
+	select FB_SVGALIB
+	---help---
+	  Driver for graphics boards with S3 Trio / S3 Virge chip.
 
 config FB_SAVAGE
 	tristate "S3 Savage support"
@@ -1625,6 +1598,26 @@
 	  Say Y here to enable support for the IBM GXT4500P display
 	  adaptor, found on some IBM System P (pSeries) machines.
 
+config FB_PS3
+	bool "PS3 GPU framebuffer driver"
+	depends on FB && PPC_PS3
+	select PS3_PS3AV
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Include support for the virtual frame buffer in the PS3 platform.
+
+config FB_PS3_DEFAULT_SIZE_M
+	int "PS3 default frame buffer size (in MiB)"
+	depends on FB_PS3
+	default 18
+	---help---
+	  This is the default size (in MiB) of the virtual frame buffer in
+	  the PS3.
+	  The default value can be overridden on the kernel command line
+	  using the "ps3fb" option (e.g. "ps3fb=9M");
+
 config FB_VIRTUAL
 	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
 	depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 309a26d..6801edf 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -17,15 +17,14 @@
 obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
 obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
 obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
+obj-$(CONFIG_FB_SVGALIB)       += svgalib.o
 obj-$(CONFIG_FB_MACMODES)      += macmodes.o
 obj-$(CONFIG_FB_DDC)           += fb_ddc.o
 
 # Hardware specific drivers go first
-obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
 obj-$(CONFIG_FB_ARC)              += arcfb.o
 obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
-obj-$(CONFIG_FB_CYBER)            += cyberfb.o
 obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
 obj-$(CONFIG_FB_PM2)              += pm2fb.o
 obj-$(CONFIG_FB_PM3)		  += pm3fb.o
@@ -43,17 +42,16 @@
 obj-$(CONFIG_FB_MBX)		  += mbx/
 obj-$(CONFIG_FB_I810)             += vgastate.o
 obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o vgastate.o
-obj-$(CONFIG_FB_VIRGE)            += virgefb.o
 obj-$(CONFIG_FB_3DFX)             += tdfxfb.o
 obj-$(CONFIG_FB_CONTROL)          += controlfb.o
 obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o
 obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o
 obj-$(CONFIG_FB_CT65550)          += chipsfb.o
 obj-$(CONFIG_FB_IMSTT)            += imsttfb.o
-obj-$(CONFIG_FB_S3TRIO)           += S3triofb.o
 obj-$(CONFIG_FB_FM2)              += fm2fb.o
 obj-$(CONFIG_FB_CYBLA)            += cyblafb.o
 obj-$(CONFIG_FB_TRIDENT)          += tridentfb.o
+obj-$(CONFIG_FB_S3)               += s3fb.o vgastate.o
 obj-$(CONFIG_FB_STI)              += stifb.o
 obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o
 obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o
@@ -75,7 +73,6 @@
 obj-$(CONFIG_FB_HP300)            += hpfb.o
 obj-$(CONFIG_FB_G364)             += g364fb.o
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
-obj-$(CONFIG_FB_SUN3)             += sun3fb.o
 obj-$(CONFIG_FB_HIT)              += hitfb.o
 obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
@@ -100,6 +97,7 @@
 obj-$(CONFIG_FB_PNX4008_DUM)	  += pnx4008/
 obj-$(CONFIG_FB_PNX4008_DUM_RGB)  += pnx4008/
 obj-$(CONFIG_FB_IBM_GXT4500)	  += gxt4500.o
+obj-$(CONFIG_FB_PS3)		  += ps3fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c
deleted file mode 100644
index b3717c8..0000000
--- a/drivers/video/S3triofb.c
+++ /dev/null
@@ -1,790 +0,0 @@
-/*
- *  linux/drivers/video/S3Triofb.c -- Open Firmware based frame buffer device
- *
- *	Copyright (C) 1997 Peter De Schrijver
- *
- *  This driver is partly based on the PowerMac console driver:
- *
- *	Copyright (C) 1996 Paul Mackerras
- *
- *  and on the Open Firmware based frame buffer device:
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-/*
-	Bugs : + OF dependencies should be removed.
-               + This driver should be merged with the CyberVision driver. The
-                 CyberVision is a Zorro III implementation of the S3Trio64 chip.
-
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <linux/pci.h>
-
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/s3blit.h>
-
-
-#define mem_in8(addr)           in_8((void *)(addr))
-#define mem_in16(addr)          in_le16((void *)(addr))
-#define mem_in32(addr)          in_le32((void *)(addr))
-
-#define mem_out8(val, addr)     out_8((void *)(addr), val)
-#define mem_out16(val, addr)    out_le16((void *)(addr), val)
-#define mem_out32(val, addr)    out_le32((void *)(addr), val)
-
-#define IO_OUT16VAL(v, r)       (((v) << 8) | (r))
-
-static struct display disp;
-static struct fb_info fb_info;
-static struct { u_char red, green, blue, pad; } palette[256];
-static char s3trio_name[16] = "S3Trio ";
-static char *s3trio_base;
-
-static struct fb_fix_screeninfo fb_fix;
-static struct fb_var_screeninfo fb_var = { 0, };
-
-
-    /*
-     *  Interface used by the world
-     */
-
-static void __init s3triofb_of_init(struct device_node *dp);
-static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con,
-			  struct fb_info *info);
-static int s3trio_get_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info);
-static int s3trio_set_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info);
-static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			   struct fb_info *info);
-static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                         u_int transp, struct fb_info *info);
-static int s3trio_pan_display(struct fb_var_screeninfo *var, int con,
-			      struct fb_info *info);
-static void s3triofb_blank(int blank, struct fb_info *info);
-
-    /*
-     *  Interface to the low level console driver
-     */
-
-int s3triofb_init(void);
-static int s3triofbcon_switch(int con, struct fb_info *info);
-static int s3triofbcon_updatevar(int con, struct fb_info *info);
-
-    /*
-     *  Text console acceleration
-     */
-
-#ifdef FBCON_HAS_CFB8
-static struct display_switch fbcon_trio8;
-#endif
-
-    /*
-     *    Accelerated Functions used by the low level console driver
-     */
-
-static void Trio_WaitQueue(u_short fifo);
-static void Trio_WaitBlit(void);
-static void Trio_BitBLT(u_short curx, u_short cury, u_short destx,
-			u_short desty, u_short width, u_short height,
-			u_short mode);
-static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height,
-			  u_short mode, u_short color);
-static void Trio_MoveCursor(u_short x, u_short y);
-
-
-    /*
-     *  Internal routines
-     */
-
-static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                         u_int *transp, struct fb_info *info);
-
-static struct fb_ops s3trio_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	s3trio_get_fix,
-	.fb_get_var =	s3trio_get_var,
-	.fb_set_var =	s3trio_set_var,
-	.fb_get_cmap =	s3trio_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	s3trio_setcolreg,
-	.fb_pan_display =s3trio_pan_display,
-	.fb_blank =	s3triofb_blank,
-};
-
-    /*
-     *  Get the Fixed Part of the Display
-     */
-
-static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con,
-			  struct fb_info *info)
-{
-    memcpy(fix, &fb_fix, sizeof(fb_fix));
-    return 0;
-}
-
-
-    /*
-     *  Get the User Defined Part of the Display
-     */
-
-static int s3trio_get_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info)
-{
-    memcpy(var, &fb_var, sizeof(fb_var));
-    return 0;
-}
-
-
-    /*
-     *  Set the User Defined Part of the Display
-     */
-
-static int s3trio_set_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info)
-{
-    if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
-	var->bits_per_pixel > fb_var.bits_per_pixel )
-	/* || var->nonstd || var->vmode != FB_VMODE_NONINTERLACED) */
-	return -EINVAL;
-    if (var->xres_virtual > fb_var.xres_virtual) {
-	outw(IO_OUT16VAL((var->xres_virtual /8) & 0xff, 0x13), 0x3d4);
-	outw(IO_OUT16VAL(((var->xres_virtual /8 ) & 0x300) >> 3, 0x51), 0x3d4);
-	fb_var.xres_virtual = var->xres_virtual;
-	fb_fix.line_length = var->xres_virtual;
-    }
-    fb_var.yres_virtual = var->yres_virtual;
-    memcpy(var, &fb_var, sizeof(fb_var));
-    return 0;
-}
-
-
-    /*
-     *  Pan or Wrap the Display
-     *
-     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-     */
-
-static int s3trio_pan_display(struct fb_var_screeninfo *var, int con,
-			      struct fb_info *info)
-{
-    unsigned int base;
-
-    if (var->xoffset > (var->xres_virtual - var->xres))
-	return -EINVAL;
-    if (var->yoffset > (var->yres_virtual - var->yres))
-	return -EINVAL;
-
-    fb_var.xoffset = var->xoffset;
-    fb_var.yoffset = var->yoffset;
-
-    base = var->yoffset * fb_fix.line_length + var->xoffset;
-
-    outw(IO_OUT16VAL((base >> 8) & 0xff, 0x0c),0x03D4);
-    outw(IO_OUT16VAL(base  & 0xff, 0x0d),0x03D4);
-    outw(IO_OUT16VAL((base >> 16) & 0xf, 0x69),0x03D4);
-    return 0;
-}
-
-
-    /*
-     *  Get the Colormap
-     */
-
-static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			   struct fb_info *info)
-{
-    if (con == info->currcon) /* current console? */
-	return fb_get_cmap(cmap, kspc, s3trio_getcolreg, info);
-    else if (fb_display[con].cmap.len) /* non default colormap? */
-	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-    else
-	fb_copy_cmap(fb_default_cmap(1 << fb_display[con].var.bits_per_pixel),
-		     cmap, kspc ? 0 : 2);
-    return 0;
-}
-
-int __init s3triofb_init(void)
-{
-	struct device_node *dp;
-
-	dp = find_devices("S3Trio");
-	if (dp != 0)
-	    s3triofb_of_init(dp);
-	return 0;
-}
-
-void __init s3trio_resetaccel(void){
-
-
-#define EC01_ENH_ENB    0x0005
-#define EC01_LAW_ENB    0x0010
-#define EC01_MMIO_ENB   0x0020
-
-#define EC00_RESET      0x8000
-#define EC00_ENABLE     0x4000
-#define MF_MULT_MISC    0xE000
-#define SRC_FOREGROUND  0x0020
-#define SRC_BACKGROUND  0x0000
-#define MIX_SRC                 0x0007
-#define MF_T_CLIP       0x1000
-#define MF_L_CLIP       0x2000
-#define MF_B_CLIP       0x3000
-#define MF_R_CLIP       0x4000
-#define MF_PIX_CONTROL  0xA000
-#define MFA_SRC_FOREGR_MIX      0x0000
-#define MF_PIX_CONTROL  0xA000
-
-	outw(EC00_RESET,  0x42e8);
-	inw(  0x42e8);
-	outw(EC00_ENABLE,  0x42e8);
-	inw(  0x42e8);
-	outw(EC01_ENH_ENB | EC01_LAW_ENB,
-		   0x4ae8);
-	outw(MF_MULT_MISC,  0xbee8); /* 16 bit I/O registers */
-
-	/* Now set some basic accelerator registers */
-	Trio_WaitQueue(0x0400);
-	outw(SRC_FOREGROUND | MIX_SRC, 0xbae8);
-	outw(SRC_BACKGROUND | MIX_SRC,  0xb6e8);/* direct color*/
-	outw(MF_T_CLIP | 0, 0xbee8 );     /* clip virtual area  */
-	outw(MF_L_CLIP | 0, 0xbee8 );
-	outw(MF_R_CLIP | (640 - 1), 0xbee8);
-	outw(MF_B_CLIP | (480 - 1),  0xbee8);
-	Trio_WaitQueue(0x0400);
-	outw(0xffff,  0xaae8);       /* Enable all planes */
-	outw(0xffff, 0xaae8);       /* Enable all planes */
-	outw( MF_PIX_CONTROL | MFA_SRC_FOREGR_MIX,  0xbee8);
-}
-
-int __init s3trio_init(struct device_node *dp){
-
-    u_char bus, dev;
-    unsigned int t32;
-    unsigned short cmd;
-
-	pci_device_loc(dp,&bus,&dev);
-                pcibios_read_config_dword(bus, dev, PCI_VENDOR_ID, &t32);
-                if(t32 == (PCI_DEVICE_ID_S3_TRIO << 16) + PCI_VENDOR_ID_S3) {
-                        pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32);
-                        pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_1, &t32);
-			pcibios_read_config_word(bus, dev, PCI_COMMAND,&cmd);
-
-			pcibios_write_config_word(bus, dev, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-
-			pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_0,0xffffffff);
-                        pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32);
-
-/* This is a gross hack as OF only maps enough memory for the framebuffer and
-   we want to use MMIO too. We should find out which chunk of address space
-   we can use here */
-			pcibios_write_config_dword(bus,dev,PCI_BASE_ADDRESS_0,0xc6000000);
-
-			/* unlock s3 */
-
-			outb(0x01, 0x3C3);
-
-			outb(inb(0x03CC) | 1, 0x3c2);
-
-			outw(IO_OUT16VAL(0x48, 0x38),0x03D4);
-			outw(IO_OUT16VAL(0xA0, 0x39),0x03D4);
-			outb(0x33,0x3d4);
-			outw(IO_OUT16VAL((inb(0x3d5) & ~(0x2 | 0x10 |  0x40)) |
-					  0x20, 0x33), 0x3d4);
-
-			outw(IO_OUT16VAL(0x6, 0x8), 0x3c4);
-
-			/* switch to MMIO only mode */
-
-			outb(0x58, 0x3d4);
-			outw(IO_OUT16VAL(inb(0x3d5) | 3 | 0x10, 0x58), 0x3d4);
-			outw(IO_OUT16VAL(8, 0x53), 0x3d4);
-
-			/* switch off I/O accesses */
-
-#if 0
-			pcibios_write_config_word(bus, dev, PCI_COMMAND,
-				        PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-#endif
-			return 1;
-                }
-
-	return 0;
-}
-
-
-    /*
-     *  Initialisation
-     *  We heavily rely on OF for the moment. This needs fixing.
-     */
-
-static void __init s3triofb_of_init(struct device_node *dp)
-{
-    int i, *pp, len;
-    unsigned long address, size;
-    u_long *CursorBase;
-
-    strncat(s3trio_name, dp->name, sizeof(s3trio_name));
-    s3trio_name[sizeof(s3trio_name)-1] = '\0';
-    strcpy(fb_fix.id, s3trio_name);
-
-    if((pp = get_property(dp, "vendor-id", &len)) != NULL
-	&& *pp!=PCI_VENDOR_ID_S3) {
-	printk("%s: can't find S3 Trio board\n", dp->full_name);
-	return;
-    }
-
-    if((pp = get_property(dp, "device-id", &len)) != NULL
-	&& *pp!=PCI_DEVICE_ID_S3_TRIO) {
-	printk("%s: can't find S3 Trio board\n", dp->full_name);
-	return;
-    }
-
-    if ((pp = get_property(dp, "depth", &len)) != NULL
-	&& len == sizeof(int) && *pp != 8) {
-	printk("%s: can't use depth = %d\n", dp->full_name, *pp);
-	return;
-    }
-    if ((pp = get_property(dp, "width", &len)) != NULL
-	&& len == sizeof(int))
-	fb_var.xres = fb_var.xres_virtual = *pp;
-    if ((pp = get_property(dp, "height", &len)) != NULL
-	&& len == sizeof(int))
-	fb_var.yres = fb_var.yres_virtual = *pp;
-    if ((pp = get_property(dp, "linebytes", &len)) != NULL
-	&& len == sizeof(int))
-	fb_fix.line_length = *pp;
-    else
-	fb_fix.line_length = fb_var.xres_virtual;
-    fb_fix.smem_len = fb_fix.line_length*fb_var.yres;
-
-    address = 0xc6000000;
-    size = 64*1024*1024;
-    if (!request_mem_region(address, size, "S3triofb"))
-	return;
-
-    s3trio_init(dp);
-    s3trio_base = ioremap(address, size);
-    fb_fix.smem_start = address;
-    fb_fix.type = FB_TYPE_PACKED_PIXELS;
-    fb_fix.type_aux = 0;
-    fb_fix.accel = FB_ACCEL_S3_TRIO64;
-    fb_fix.mmio_start = address+0x1000000;
-    fb_fix.mmio_len = 0x1000000;
-
-    fb_fix.xpanstep = 1;
-    fb_fix.ypanstep = 1;
-
-    s3trio_resetaccel();
-
-    mem_out8(0x30, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0x2d, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0x2e, s3trio_base+0x1008000 + 0x03D4);
-
-    mem_out8(0x50, s3trio_base+0x1008000 + 0x03D4);
-
-    /* disable HW cursor */
-
-    mem_out8(0x39, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0xa0, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x4e, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x4f, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
-
-    /* init HW cursor */
-
-    CursorBase = (u_long *)(s3trio_base + 2*1024*1024 - 0x400);
-	for (i = 0; i < 8; i++) {
-		*(CursorBase  +(i*4)) = 0xffffff00;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
-	}
-	for (i = 8; i < 64; i++) {
-		*(CursorBase  +(i*4)) = 0xffff0000;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
-	}
-
-
-    mem_out8(0x4c, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(((2*1024 - 1)&0xf00)>>8, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x4d, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8((2*1024 - 1) & 0xff, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4);
-    mem_in8(s3trio_base+0x1008000 + 0x03D4);
-
-    mem_out8(0x4a, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5);
-    mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5);
-    mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x4b, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5);
-    mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5);
-    mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5);
-
-    mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4);
-    mem_out8(0, s3trio_base+0x1008000 + 0x03D5);
-
-    /* setup default color table */
-
-	for(i = 0; i < 16; i++) {
-		int j = color_table[i];
-		palette[i].red=default_red[j];
-		palette[i].green=default_grn[j];
-		palette[i].blue=default_blu[j];
-	}
-
-    s3trio_setcolreg(255, 56, 100, 160, 0, NULL /* not used */);
-    s3trio_setcolreg(254, 0, 0, 0, 0, NULL /* not used */);
-    memset((char *)s3trio_base, 0, 640*480);
-
-#if 0
-    Trio_RectFill(0, 0, 90, 90, 7, 1);
-#endif
-
-    fb_fix.visual = FB_VISUAL_PSEUDOCOLOR ;
-    fb_var.xoffset = fb_var.yoffset = 0;
-    fb_var.bits_per_pixel = 8;
-    fb_var.grayscale = 0;
-    fb_var.red.offset = fb_var.green.offset = fb_var.blue.offset = 0;
-    fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
-    fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
-    fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
-    fb_var.nonstd = 0;
-    fb_var.activate = 0;
-    fb_var.height = fb_var.width = -1;
-    fb_var.accel_flags = FB_ACCELF_TEXT;
-#warning FIXME: always obey fb_var.accel_flags
-    fb_var.pixclock = 1;
-    fb_var.left_margin = fb_var.right_margin = 0;
-    fb_var.upper_margin = fb_var.lower_margin = 0;
-    fb_var.hsync_len = fb_var.vsync_len = 0;
-    fb_var.sync = 0;
-    fb_var.vmode = FB_VMODE_NONINTERLACED;
-
-    disp.var = fb_var;
-    disp.cmap.start = 0;
-    disp.cmap.len = 0;
-    disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
-    disp.visual = fb_fix.visual;
-    disp.type = fb_fix.type;
-    disp.type_aux = fb_fix.type_aux;
-    disp.ypanstep = 0;
-    disp.ywrapstep = 0;
-    disp.line_length = fb_fix.line_length;
-    disp.can_soft_blank = 1;
-    disp.inverse = 0;
-#ifdef FBCON_HAS_CFB8
-    if (fb_var.accel_flags & FB_ACCELF_TEXT)
-	disp.dispsw = &fbcon_trio8;
-    else
-	disp.dispsw = &fbcon_cfb8;
-#else
-    disp.dispsw = &fbcon_dummy;
-#endif
-    disp.scrollmode = fb_var.accel_flags & FB_ACCELF_TEXT ? 0 : SCROLL_YREDRAW;
-
-    strcpy(fb_info.modename, "Trio64 ");
-    strncat(fb_info.modename, dp->full_name, sizeof(fb_info.modename));
-    fb_info.currcon = -1;
-    fb_info.fbops = &s3trio_ops;
-    fb_info.screen_base = s3trio_base;	
-#if 0
-    fb_info.fbvar_num = 1;
-    fb_info.fbvar = &fb_var;
-#endif
-    fb_info.disp = &disp;
-    fb_info.fontname[0] = '\0';
-    fb_info.changevar = NULL;
-    fb_info.switch_con = &s3triofbcon_switch;
-    fb_info.updatevar = &s3triofbcon_updatevar;
-#if 0
-    fb_info.setcmap = &s3triofbcon_setcmap;
-#endif
-
-    fb_info.flags = FBINFO_FLAG_DEFAULT;
-    if (register_framebuffer(&fb_info) < 0) {
-		iounmap(fb_info.screen_base);
-		fb_info.screen_base = NULL;
-		return;
-    }
-
-    printk("fb%d: S3 Trio frame buffer device on %s\n",
-	   fb_info.node, dp->full_name);
-}
-
-
-static int s3triofbcon_switch(int con, struct fb_info *info)
-{
-    /* Do we have to save the colormap? */
-    if (fb_display[info->currcon].cmap.len)
-	fb_get_cmap(&fb_display[info->currcon].cmap, 1, s3trio_getcolreg, info);
-
-    info->currcon = con;
-    /* Install new colormap */
-    do_install_cmap(con,info);
-    return 0;
-}
-
-    /*
-     *  Update the `var' structure (called by fbcon.c)
-     */
-
-static int s3triofbcon_updatevar(int con, struct fb_info *info)
-{
-    /* Nothing */
-    return 0;
-}
-
-    /*
-     *  Blank the display.
-     */
-
-static int s3triofb_blank(int blank, struct fb_info *info)
-{
-    unsigned char x;
-
-    mem_out8(0x1, s3trio_base+0x1008000 + 0x03c4);
-    x = mem_in8(s3trio_base+0x1008000 + 0x03c5);
-    mem_out8((x & (~0x20)) | (blank << 5), s3trio_base+0x1008000 + 0x03c5);
-    return 0;	
-}
-
-    /*
-     *  Read a single color register and split it into
-     *  colors/transparent. Return != 0 for invalid regno.
-     */
-
-static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                         u_int *transp, struct fb_info *info)
-{
-    if (regno > 255)
-	return 1;
-    *red = (palette[regno].red << 8) | palette[regno].red;
-    *green = (palette[regno].green << 8) | palette[regno].green;
-    *blue = (palette[regno].blue << 8) | palette[regno].blue;
-    *transp = 0;
-    return 0;
-}
-
-
-    /*
-     *  Set a single color register. Return != 0 for invalid regno.
-     */
-
-static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                            u_int transp, struct fb_info *info)
-{
-    if (regno > 255)
-	return 1;
-
-    red >>= 8;
-    green >>= 8;
-    blue >>= 8;
-    palette[regno].red = red;
-    palette[regno].green = green;
-    palette[regno].blue = blue;
-
-    mem_out8(regno,s3trio_base+0x1008000 + 0x3c8);
-    mem_out8((red & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9);
-    mem_out8((green & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9);
-    mem_out8((blue & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9);
-
-    return 0;
-}
-
-static void Trio_WaitQueue(u_short fifo) {
-
-	u_short status;
-
-        do
-        {
-		status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8);
-	}  while (!(status & fifo));
-
-}
-
-static void Trio_WaitBlit(void) {
-
-	u_short status;
-
-        do
-        {
-		status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8);
-	}  while (status & 0x200);
-
-}
-
-static void Trio_BitBLT(u_short curx, u_short cury, u_short destx,
-			u_short desty, u_short width, u_short height,
-			u_short mode) {
-
-	u_short blitcmd = 0xc011;
-
-	/* Set drawing direction */
-        /* -Y, X maj, -X (default) */
-
-	if (curx > destx)
-		blitcmd |= 0x0020;  /* Drawing direction +X */
-	else {
-		curx  += (width - 1);
-		destx += (width - 1);
-	}
-
-	if (cury > desty)
-		blitcmd |= 0x0080;  /* Drawing direction +Y */
-	else {
-		cury  += (height - 1);
-		desty += (height - 1);
-	}
-
-	Trio_WaitQueue(0x0400);
-
-	outw(0xa000,  0xBEE8);
-	outw(0x60 | mode,  0xBAE8);
-
-	outw(curx,  0x86E8);
-	outw(cury,  0x82E8);
-
-	outw(destx,  0x8EE8);
-	outw(desty,  0x8AE8);
-
-	outw(height - 1,  0xBEE8);
-	outw(width - 1,  0x96E8);
-
-	outw(blitcmd,  0x9AE8);
-
-}
-
-static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height,
-			  u_short mode, u_short color) {
-
-	u_short blitcmd = 0x40b1;
-
-	Trio_WaitQueue(0x0400);
-
-	outw(0xa000,  0xBEE8);
-	outw((0x20 | mode),  0xBAE8);
-	outw(0xe000,  0xBEE8);
-	outw(color,  0xA6E8);
-	outw(x,  0x86E8);
-	outw(y,  0x82E8);
-	outw((height - 1), 0xBEE8);
-	outw((width - 1), 0x96E8);
-	outw(blitcmd,  0x9AE8);
-
-}
-
-
-static void Trio_MoveCursor(u_short x, u_short y) {
-
-	mem_out8(0x39, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8(0xa0, s3trio_base + 0x1008000 + 0x3d5);
-
-	mem_out8(0x46, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8((x & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5);
-	mem_out8(0x47, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8(x & 0x00ff, s3trio_base + 0x1008000 + 0x3d5);
-
-	mem_out8(0x48, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8((y & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5);
-	mem_out8(0x49, s3trio_base + 0x1008000 + 0x3d4);
-	mem_out8(y & 0x00ff, s3trio_base + 0x1008000 + 0x3d5);
-
-}
-
-
-    /*
-     *  Text console acceleration
-     */
-
-#ifdef FBCON_HAS_CFB8
-static void fbcon_trio8_bmove(struct display *p, int sy, int sx, int dy,
-			      int dx, int height, int width)
-{
-    sx *= 8; dx *= 8; width *= 8;
-    Trio_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-		 (u_short)(dy*fontheight(p)), (u_short)width,
-		 (u_short)(height*fontheight(p)), (u_short)S3_NEW);
-}
-
-static void fbcon_trio8_clear(struct vc_data *conp, struct display *p, int sy,
-			      int sx, int height, int width)
-{
-    unsigned char bg;
-
-    sx *= 8; width *= 8;
-    bg = attr_bgcol_ec(p,conp);
-    Trio_RectFill((u_short)sx,
-		   (u_short)(sy*fontheight(p)),
-		   (u_short)width,
-		   (u_short)(height*fontheight(p)),
-		   (u_short)S3_NEW,
-		   (u_short)bg);
-}
-
-static void fbcon_trio8_putc(struct vc_data *conp, struct display *p, int c,
-			     int yy, int xx)
-{
-    Trio_WaitBlit();
-    fbcon_cfb8_putc(conp, p, c, yy, xx);
-}
-
-static void fbcon_trio8_putcs(struct vc_data *conp, struct display *p,
-			      const unsigned short *s, int count, int yy, int xx)
-{
-    Trio_WaitBlit();
-    fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
-}
-
-static void fbcon_trio8_revc(struct display *p, int xx, int yy)
-{
-    Trio_WaitBlit();
-    fbcon_cfb8_revc(p, xx, yy);
-}
-
-static struct display_switch fbcon_trio8 = {
-   .setup =		fbcon_cfb8_setup,
-   .bmove =		fbcon_trio8_bmove,
-   .clear =		fbcon_trio8_clear,
-   .putc =		fbcon_trio8_putc,
-   .putcs =		fbcon_trio8_putcs,
-   .revc =		fbcon_trio8_revc,
-   .clear_margins =	fbcon_cfb8_clear_margins,
-   .fontwidthmask =	FONTWIDTH(8)
-};
-#endif
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index f2ebdd8..301612c 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2566,7 +2566,7 @@
 	       info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max,
 	       par->pll_limits.mclk, par->pll_limits.xclk);
 
-#if defined(DEBUG) && defined(CONFIG_ATY_CT)
+#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
 	if (M64_HAS(INTEGRATED)) {
 		int i;
 		printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
@@ -2957,8 +2957,6 @@
 static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
 			struct fb_info *info, unsigned long addr)
 {
-	extern int con_is_present(void);
-
 	struct atyfb_par *par = info->par;
 	struct pcidev_cookie *pcp;
 	char prop[128];
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index ef5c16f..80a81ec 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -468,11 +468,10 @@
 			return -EINVAL;
 
 	/* Allocate new device private */
-	if (!(fbdev = kmalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) {
+	if (!(fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) {
 		print_err("fail to allocate device private record");
 		return -ENOMEM;
 	}
-	memset((void*)fbdev, 0, sizeof(struct au1100fb_device));
 
 	fbdev->panel = &known_lcd_panels[drv_info.panel_idx];
 
@@ -549,10 +548,9 @@
 	fbdev->info.fbops = &au1100fb_ops;
 	fbdev->info.fix = au1100fb_fix;
 
-	if (!(fbdev->info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL))) {
+	if (!(fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL))) {
 		return -ENOMEM;
 	}
-	memset(fbdev->info.pseudo_palette, 0, sizeof(u32) * 16);
 
 	if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
 		print_err("Fail to allocate colormap (%d entries)",
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 31f476a..ce5ac26 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2071,7 +2071,7 @@
 	y_diff = info->var.yres - var.yres;
 	if (x_diff < 0 || x_diff > virt_fw ||
 	    y_diff < 0 || y_diff > virt_fh) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
 		mode = fb_find_best_mode(&var, &info->modelist);
@@ -2975,7 +2975,7 @@
 	int i;
 	struct vc_data *vc;
 	struct fb_var_screeninfo var;
-	struct fb_videomode *mode;
+	const struct fb_videomode *mode;
 
 	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (registered_fb[con2fb_map[i]] != info)
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index b9386d1..71f24e0 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -48,7 +48,7 @@
     struct fb_bitfield green;
     struct fb_bitfield blue;
     struct fb_bitfield transp;
-    struct fb_videomode *mode;
+    const struct fb_videomode *mode;
 };
 
 struct fbcon_ops {
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 04c6d92..fd60dba 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -696,11 +696,10 @@
 		printk(KERN_ERR "can't get 2 addresses for control\n");
 		return -ENXIO;
 	}
-	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
 	if (p == 0)
 		return -ENXIO;
 	control_fb = p;	/* save it for cleanups */
-	memset(p, 0, sizeof(*p));
 
 	/* Map in frame buffer and registers */
 	p->fb_orig_base = fb_res.start;
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index aae6d9c..7a6eeda 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1539,16 +1539,21 @@
 	/*
 	 * Allow the CyberPro to accept PCI burst accesses
 	 */
-	val = cyber2000_grphr(EXT_BUS_CTL, cfb);
-	if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
-		printk(KERN_INFO "%s: enabling PCI bursts\n", cfb->fb.fix.id);
+	if (cfb->id == ID_CYBERPRO_2010) {
+		printk(KERN_INFO "%s: NOT enabling PCI bursts\n", cfb->fb.fix.id);
+	} else {
+		val = cyber2000_grphr(EXT_BUS_CTL, cfb);
+		if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
+			printk(KERN_INFO "%s: enabling PCI bursts\n",
+				cfb->fb.fix.id);
 
-		val |= EXT_BUS_CTL_PCIBURST_WRITE;
+			val |= EXT_BUS_CTL_PCIBURST_WRITE;
 
-		if (cfb->id == ID_CYBERPRO_5000)
-			val |= EXT_BUS_CTL_PCIBURST_READ;
+			if (cfb->id == ID_CYBERPRO_5000)
+				val |= EXT_BUS_CTL_PCIBURST_READ;
 
-		cyber2000_grphw(EXT_BUS_CTL, val, cfb);
+			cyber2000_grphw(EXT_BUS_CTL, val, cfb);
+		}
 	}
 
 	return 0;
diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c
deleted file mode 100644
index 0b8d5b1..0000000
--- a/drivers/video/cyberfb.c
+++ /dev/null
@@ -1,2295 +0,0 @@
-/*
-* linux/drivers/video/cyberfb.c -- CyberVision64 frame buffer device
-* $Id: cyberfb.c,v 1.6 1998/09/11 04:54:58 abair Exp $
-*
-*    Copyright (C) 1998 Alan Bair
-*
-* This file is based on two CyberVision64 frame buffer device drivers
-*
-* The second CyberVision64 frame buffer device (cvision.c cvision_core.c):
-*
-*   Copyright (c) 1997 Antonio Santos
-*
-* Released as a patch to 2.1.35, but never included in the source tree.
-* This is based on work from the NetBSD CyberVision64 frame buffer driver 
-* and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
-* Permission to use the source of this driver was obtained from the
-* author Michael Teske by Alan Bair.
-*
-*   Copyright (c) 1995 Michael Teske
-*
-* The first CyberVision64 frame buffer device (cyberfb.c):
-*
-*    Copyright (C) 1996 Martin Apel
-*                       Geert Uytterhoeven
-*
-* Which is based on the Amiga frame buffer device (amifb.c):
-*
-*    Copyright (C) 1995 Geert Uytterhoeven
-*
-*
-* History:
-*   - 22 Dec 95: Original version by Martin Apel
-*   - 05 Jan 96: Geert: integration into the current source tree
-*   - 01 Aug 98: Alan: Merge in code from cvision.c and cvision_core.c
-* $Log: cyberfb.c,v $
-* Revision 1.6  1998/09/11 04:54:58  abair
-* Update for 2.1.120 change in include file location.
-* Clean up for public release.
-*
-* Revision 1.5  1998/09/03 04:27:13  abair
-* Move cv64_load_video_mode to cyber_set_video so a new video mode is install
-* with each change of the 'var' data.
-*
-* Revision 1.4  1998/09/01 00:31:17  abair
-* Put in a set of default 8,16,24 bpp modes and map cyber8,16 to them.
-* Update operations with 'par' to handle a more complete set of parameter
-* values for encode/decode process.
-*
-* Revision 1.3  1998/08/31 21:31:33  abair
-* Swap 800x490 for 640x480 video mode and more cleanup.
-* Abandon idea to resurrect "custom" mode setting via kernel opts,
-* instead work on making use of fbset program to do this.
-*
-* Revision 1.2  1998/08/31 06:17:08  abair
-* Make updates for changes in cyberfb.c released in 2.1.119
-* and do some cleanup of the code.
-*
-* Revision 1.1  1998/08/29 18:38:31  abair
-* Initial revision
-*
-* Revision 1.3  1998/08/17 06:21:53  abair
-* Remove more redundant code after merging in cvision_core.c
-* Set blanking by colormap to pale red to detect this vs trying to
-* use video blanking. More formating to Linux code style.
-*
-* Revision 1.2  1998/08/15 17:51:37  abair
-* Added cvision_core.c code from 2.1.35 patches.
-* Changed to compile correctly and switch to using initialization
-* code. Added debugging and dropping of duplicate code.
-*
-*
-*
-* This file is subject to the terms and conditions of the GNU General Public
-* License.  See the file COPYING in the main directory of this archive
-* for more details.
-*/
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/zorro.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/amigahw.h>
-#include <asm/io.h>
-
-#include "cyberfb.h"
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-
-/*#define CYBERFBDEBUG*/
-#ifdef CYBERFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-static void cv64_dump(void);
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
-#define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
-
-struct cyberfb_par {
-	struct fb_var_screeninfo var;
-	__u32 type;
-	__u32 type_aux;
-	__u32 visual;
-	__u32 line_length;
-};
-
-static struct cyberfb_par current_par;
-
-static int current_par_valid = 0;
-
-static struct display disp;
-static struct fb_info fb_info;
-
-
-/*
- *    Frame Buffer Name
- */
-
-static char cyberfb_name[16] = "Cybervision";
-
-
-/*
- *    CyberVision Graphics Board
- */
-
-static unsigned char Cyber_colour_table [256][3];
-static unsigned long CyberSize;
-static volatile unsigned char *CyberBase;
-static volatile unsigned char *CyberMem;
-static volatile unsigned char *CyberRegs;
-static unsigned long CyberMem_phys;
-static unsigned long CyberRegs_phys;
-
-/*
- *    Predefined Video Modes
- */
-
-static struct {
-    const char *name;
-    struct fb_var_screeninfo var;
-} cyberfb_predefined[] __initdata = {
-	{ "640x480-8", {		/* Default 8 BPP mode (cyber8) */
-		640, 480, 640, 480, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
-		FB_VMODE_NONINTERLACED
-	}}, 
-	{ "640x480-16", {		/* Default 16 BPP mode (cyber16) */
-		640, 480, 640, 480, 0, 0, 16, 0,
-		{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
-		FB_VMODE_NONINTERLACED
-	}}, 
-	{ "640x480-24", {		/* Default 24 BPP mode */
-		640, 480, 640, 480, 0, 0, 24, 0,
-		{16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
-		FB_VMODE_NONINTERLACED
-	}}, 
-	{ "800x490-8", {		/* Cybervision 8 bpp */
-		/* NO Acceleration */
-		800, 490, 800, 490, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED
-	}},
-/* I can't test these with my monitor, but I suspect they will
- * be OK, since Antonio Santos indicated he had tested them in
- * his system.
- */
-	{ "800x600-8", {		/* Cybervision 8 bpp */
-		800, 600, 800, 600, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 2,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED
-	}},
-	{ "1024x768-8", {		/* Cybervision 8 bpp */
-		1024, 768, 1024, 768, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 224, 72, 60, 12, 168, 4,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED
-	}},
-	{ "1152x886-8", {		/* Cybervision 8 bpp */
-		1152, 886, 1152, 886, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 15873, 184, 40, 24, 1, 56, 16,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_NONINTERLACED
-	}},
-	{ "1280x1024-8", {	/* Cybervision 8 bpp */
-		1280, 1024, 1280, 1024, 0, 0, 8, 0,
-		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-		0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 256, 48, 50, 12, 72, 4,
-		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
-		FB_VMODE_INTERLACED
-	}}
-};
-
-#define NUM_TOTAL_MODES    ARRAY_SIZE(cyberfb_predefined)
-
-static int Cyberfb_inverse = 0;
-
-/*
- *    Some default modes
- */
-
-#define CYBER8_DEFMODE     (0)
-#define CYBER16_DEFMODE    (1)
-
-static struct fb_var_screeninfo cyberfb_default;
-static int cyberfb_usermode __initdata = 0;
-
-/*
- *    Interface used by the world
- */
-
-int cyberfb_setup(char *options);
-
-static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info);
-static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info);
-static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info);
-static int cyberfb_blank(int blank, struct fb_info *info);
-
-/*
- *    Interface to the low level console driver
- */
-
-int cyberfb_init(void);
-static int Cyberfb_switch(int con, struct fb_info *info);
-static int Cyberfb_updatevar(int con, struct fb_info *info);
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static struct display_switch fbcon_cyber8;
-#endif
-
-/*
- *    Accelerated Functions used by the low level console driver
- */
-
-static void Cyber_WaitQueue(u_short fifo);
-static void Cyber_WaitBlit(void);
-static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
-			 u_short desty, u_short width, u_short height,
-			 u_short mode);
-static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
-			   u_short mode, u_short color);
-#if 0
-static void Cyber_MoveCursor(u_short x, u_short y);
-#endif
-
-/*
- *   Hardware Specific Routines
- */
-
-static int Cyber_init(void);
-static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
-			    struct cyberfb_par *par);
-static int Cyber_decode_var(struct fb_var_screeninfo *var,
-			    struct cyberfb_par *par);
-static int Cyber_encode_var(struct fb_var_screeninfo *var,
-			    struct cyberfb_par *par);
-static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			   u_int *transp, struct fb_info *info);
-
-/*
- *    Internal routines
- */
-
-static void cyberfb_get_par(struct cyberfb_par *par);
-static void cyberfb_set_par(struct cyberfb_par *par);
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
-static void cyberfb_set_disp(int con, struct fb_info *info);
-static int get_video_mode(const char *name);
-
-/* For cvision_core.c */
-static unsigned short cv64_compute_clock(unsigned long);
-static int cv_has_4mb (volatile unsigned char *);
-static void cv64_board_init (void);
-static void cv64_load_video_mode (struct fb_var_screeninfo *);
-
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-
-/*
- *    Initialization
- *
- *    Set the default video mode for this chipset. If a video mode was
- *    specified on the command line, it will override the default mode.
- */
-
-static int Cyber_init(void)
-{
-	volatile unsigned char *regs = CyberRegs;
-	volatile unsigned long *CursorBase;
-	int i;
-	DPRINTK("ENTER\n");
-
-/* Init local cmap as greyscale levels */
-	for (i = 0; i < 256; i++) {
-		Cyber_colour_table [i][0] = i;
-		Cyber_colour_table [i][1] = i;
-		Cyber_colour_table [i][2] = i;
-	}
-
-/* Initialize the board and determine fbmem size */
-	cv64_board_init(); 
-#ifdef CYBERFBDEBUG
-	DPRINTK("Register state after initing board\n");
-	cv64_dump();
-#endif
-/* Clear framebuffer memory */
-	DPRINTK("Clear framebuffer memory\n");
-	memset ((char *)CyberMem, 0, CyberSize);
-
-/* Disable hardware cursor */
-	DPRINTK("Disable HW cursor\n");
-	wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2);
-	wb_64(regs, S3_CRTC_DATA, 0xa0);
-	wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE);
-	wb_64(regs, S3_CRTC_DATA, 0x00);
-	wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX);
-	wb_64(regs, S3_CRTC_DATA, 0x00);
-	wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY);
-	wb_64(regs, S3_CRTC_DATA, 0x00);
-
-/* Initialize hardware cursor */
-	DPRINTK("Init HW cursor\n");
-	CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
-	for (i=0; i < 8; i++)
-	{
-		*(CursorBase  +(i*4)) = 0xffffff00;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
-	}
-	for (i=8; i < 64; i++)
-	{
-		*(CursorBase  +(i*4)) = 0xffff0000;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
-	}
-
-	cyberfb_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
-	cyberfb_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
-
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    This function should fill in the `fix' structure based on the
- *    values in the `par' structure.
- */
-
-static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
-			    struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, cyberfb_name);
-	fix->smem_start = CyberMem_phys;
-	fix->smem_len = CyberSize;
-	fix->mmio_start = CyberRegs_phys;
-	fix->mmio_len = 0x10000;
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-	if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 ||
-	    par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) {
-		fix->visual = FB_VISUAL_DIRECTCOLOR;
-	} else {
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	}
-
-	fix->xpanstep = 0;
-	fix->ypanstep = 0;
-	fix->ywrapstep = 0;
-	fix->line_length = 0;
-	fix->accel = FB_ACCEL_S3_TRIO64;
-
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-
-/*
-*    Fill the `par' structure based on the values in `var'.
-*    TODO: Verify and adjust values, return -EINVAL if bad.
-*/
-
-static int Cyber_decode_var(struct fb_var_screeninfo *var,
-			    struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	par->var.xres = var->xres;
-	par->var.yres = var->yres;
-	par->var.xres_virtual = var->xres_virtual;
-	par->var.yres_virtual = var->yres_virtual;
-	par->var.xoffset = var->xoffset;
-	par->var.yoffset = var->yoffset;
-	par->var.bits_per_pixel = var->bits_per_pixel;
-	par->var.grayscale = var->grayscale;
-	par->var.red = var->red;
-	par->var.green = var->green;
-	par->var.blue = var->blue;
-	par->var.transp = var->transp;
-	par->var.nonstd = var->nonstd;
-	par->var.activate = var->activate;
-	par->var.height = var->height;
-	par->var.width = var->width;
-	if (var->accel_flags & FB_ACCELF_TEXT) {
-		par->var.accel_flags = FB_ACCELF_TEXT;
-	} else {
-		par->var.accel_flags = 0;
-	}
-	par->var.pixclock = var->pixclock;
-	par->var.left_margin = var->left_margin;
-	par->var.right_margin = var->right_margin;
-	par->var.upper_margin = var->upper_margin;
-	par->var.lower_margin = var->lower_margin;
-	par->var.hsync_len = var->hsync_len;
-	par->var.vsync_len = var->vsync_len;
-	par->var.sync = var->sync;
-	par->var.vmode = var->vmode;
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-/*
-*    Fill the `var' structure based on the values in `par' and maybe
-*    other values read out of the hardware.
-*/
-
-static int Cyber_encode_var(struct fb_var_screeninfo *var,
-			    struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	var->xres = par->var.xres;
-	var->yres = par->var.yres;
-	var->xres_virtual = par->var.xres_virtual;
-	var->yres_virtual = par->var.yres_virtual;
-	var->xoffset = par->var.xoffset;
-	var->yoffset = par->var.yoffset;
-
-	var->bits_per_pixel = par->var.bits_per_pixel;
-	var->grayscale = par->var.grayscale;
-
-	var->red = par->var.red;
-	var->green = par->var.green;
-	var->blue = par->var.blue;
-	var->transp = par->var.transp;
-
-	var->nonstd = par->var.nonstd;
-	var->activate = par->var.activate;
-
-	var->height = par->var.height;
-	var->width = par->var.width;
-
-	var->accel_flags = par->var.accel_flags;
-
-	var->pixclock = par->var.pixclock;
-	var->left_margin = par->var.left_margin;
-	var->right_margin = par->var.right_margin;
-	var->upper_margin = par->var.upper_margin;
-	var->lower_margin = par->var.lower_margin;
-	var->hsync_len = par->var.hsync_len;
-	var->vsync_len = par->var.vsync_len;
-	var->sync = par->var.sync;
-	var->vmode = par->var.vmode;
-	
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-
-/*
- *    Set a single color register. Return != 0 for invalid regno.
- */
-
-static int cyberfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info)
-{
-	volatile unsigned char *regs = CyberRegs;
-
-	/*DPRINTK("ENTER\n");*/
-	if (regno > 255) {
-		DPRINTK("EXIT - Register # > 255\n");
-		return (1);
-	}
-
-	wb_64(regs, 0x3c8, (unsigned char) regno);
-
- 	red >>= 10;
- 	green >>= 10;
- 	blue >>= 10;
-
-	Cyber_colour_table [regno][0] = red;
-	Cyber_colour_table [regno][1] = green;
-	Cyber_colour_table [regno][2] = blue;
-
-	wb_64(regs, 0x3c9, red);
-	wb_64(regs, 0x3c9, green);
-	wb_64(regs, 0x3c9, blue);
-
-	/*DPRINTK("EXIT\n");*/
-	return (0);
-}
-
-
-/*
-*    Read a single color register and split it into
-*    colors/transparent. Return != 0 for invalid regno.
-*/
-
-static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			   u_int *transp, struct fb_info *info)
-{
-	int t;
-
-	/*DPRINTK("ENTER\n");*/
-	if (regno > 255) {
-		DPRINTK("EXIT - Register # > 255\n");
-		return (1);
-	}
-	/* ARB This shifting & oring seems VERY strange */
- 	t	= Cyber_colour_table [regno][0];
- 	*red	= (t<<10) | (t<<4) | (t>>2);
- 	t	= Cyber_colour_table [regno][1];
- 	*green	= (t<<10) | (t<<4) | (t>>2);
- 	t	= Cyber_colour_table [regno][2];
- 	*blue	= (t<<10) | (t<<4) | (t>>2);
- 	*transp = 0;
-	/*DPRINTK("EXIT\n");*/
-	return (0);
-}
-
-
-/*
-*    (Un)Blank the screen
-*    blank: 1 = zero fb cmap
-*           0 = restore fb cmap from local cmap
-*/
-static int cyberfb_blank(int blank, struct fb_info *info)
-{
-	volatile unsigned char *regs = CyberRegs;
-	int i;
-
-	DPRINTK("ENTER\n");
-#if 0
-/* Blank by turning gfx off */
-	gfx_on_off (1, regs);
-#else
-	if (blank) {
-		for (i = 0; i < 256; i++) {
-			wb_64(regs, 0x3c8, (unsigned char) i);
-			/* ARB Pale red to detect this blanking method */
-			wb_64(regs, 0x3c9, 48); 
-			wb_64(regs, 0x3c9, 0);
-			wb_64(regs, 0x3c9, 0);
-		}
-	} else {
-		for (i = 0; i < 256; i++) {
-			wb_64(regs, 0x3c8, (unsigned char) i);
-			wb_64(regs, 0x3c9, Cyber_colour_table[i][0]);
-			wb_64(regs, 0x3c9, Cyber_colour_table[i][1]);
-			wb_64(regs, 0x3c9, Cyber_colour_table[i][2]);
-		}
-	}
-#endif
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/**************************************************************
- * We are waiting for "fifo" FIFO-slots empty
- */
-static void Cyber_WaitQueue (u_short fifo)
-{
-	unsigned short status;
-
-	DPRINTK("ENTER\n");
-	do {
-		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
-	} while (status & fifo);
-	DPRINTK("EXIT\n");
-}
-
-/**************************************************************
- * We are waiting for Hardware (Graphics Engine) not busy
- */
-static void Cyber_WaitBlit (void)
-{
-	unsigned short status;
-
-	DPRINTK("ENTER\n");
-	do {
-		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
-	} while (status & S3_HDW_BUSY);
-	DPRINTK("EXIT\n");
-}
-
-/**************************************************************
- * BitBLT - Through the Plane
- */
-static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
-			  u_short desty, u_short width, u_short height,
-			  u_short mode)
-{
-	volatile unsigned char *regs = CyberRegs;
-	u_short blitcmd = S3_BITBLT;
-
-	DPRINTK("ENTER\n");
-	/* Set drawing direction */
-	/* -Y, X maj, -X (default) */
-	if (curx > destx) {
-		blitcmd |= 0x0020;  /* Drawing direction +X */
-	} else {
-		curx  += (width - 1);
-		destx += (width - 1);
-	}
-
-	if (cury > desty) {
-		blitcmd |= 0x0080;  /* Drawing direction +Y */
-	} else {
-		cury  += (height - 1);
-		desty += (height - 1);
-	}
-
-	Cyber_WaitQueue (0x8000);
-
-	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
-	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
-
-	*((u_short volatile *)(regs + S3_CUR_X)) = curx;
-	*((u_short volatile *)(regs + S3_CUR_Y)) = cury;
-
-	*((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
-	*((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
-
-	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
-	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
-
-	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
-	DPRINTK("EXIT\n");
-}
-
-/**************************************************************
- * Rectangle Fill Solid
- */
-static void Cyber_RectFill (u_short x, u_short y, u_short width,
-			    u_short height, u_short mode, u_short color)
-{
-	volatile unsigned char *regs = CyberRegs;
-	u_short blitcmd = S3_FILLEDRECT;
-
-	DPRINTK("ENTER\n");
-	Cyber_WaitQueue (0x8000);
-
-	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
-	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
-
-	*((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
-	*((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
-
-	*((u_short volatile *)(regs + S3_CUR_X)) = x;
-	*((u_short volatile *)(regs + S3_CUR_Y)) = y;
-
-	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
-	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
-
-	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
-	DPRINTK("EXIT\n");
-}
-
-
-#if 0
-/**************************************************************
- * Move cursor to x, y
- */
-static void Cyber_MoveCursor (u_short x, u_short y)
-{
-	volatile unsigned char *regs = CyberRegs;
-	DPRINTK("ENTER\n");
-	*(regs + S3_CRTC_ADR)  = 0x39;
-	*(regs + S3_CRTC_DATA) = 0xa0;
-
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
-	*(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
-	*(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
-
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
-	*(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
-	*(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
-	DPRINTK("EXIT\n");
-}
-#endif
-
-
-/* -------------------- Generic routines ---------------------------------- */
-
-
-/*
- *    Fill the hardware's `par' structure.
- */
-
-static void cyberfb_get_par(struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	if (current_par_valid) {
-		*par = current_par;
-	} else {
-		Cyber_decode_var(&cyberfb_default, par);
-	}
-	DPRINTK("EXIT\n");
-}
-
-
-static void cyberfb_set_par(struct cyberfb_par *par)
-{
-	DPRINTK("ENTER\n");
-	current_par = *par;
-	current_par_valid = 1;
-	DPRINTK("EXIT\n");
-}
-
-
-static void cyber_set_video(struct fb_var_screeninfo *var)
-{
-
-	/* Load the video mode defined by the 'var' data */
-	cv64_load_video_mode (var);
-#ifdef CYBERFBDEBUG
-	DPRINTK("Register state after loading video mode\n");
-	cv64_dump();
-#endif
-}
-
-
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
-{
-	int err, activate;
-	struct cyberfb_par par;
-
-	DPRINTK("ENTER\n");
-	if ((err = Cyber_decode_var(var, &par))) {
-		DPRINTK("EXIT - decode_var failed\n");
-		return(err);
-	}
-	activate = var->activate;
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
-		cyberfb_set_par(&par);
-	Cyber_encode_var(var, &par);
-	var->activate = activate;
-
-	cyber_set_video(var);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *    Get the Fixed Part of the Display
- */
-
-static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info)
-{
-	struct cyberfb_par par;
-	int error = 0;
-
-	DPRINTK("ENTER\n");
-	if (con == -1) {
-		cyberfb_get_par(&par);
-	} else {
-		error = Cyber_decode_var(&fb_display[con].var, &par);
-	}
-	DPRINTK("EXIT\n");
-	return(error ? error : Cyber_encode_fix(fix, &par));
-}
-
-
-/*
- *    Get the User Defined Part of the Display
- */
-
-static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	struct cyberfb_par par;
-	int error = 0;
-
-	DPRINTK("ENTER\n");
-	if (con == -1) {
-		cyberfb_get_par(&par);
-		error = Cyber_encode_var(var, &par);
-		disp.var = *var;   /* ++Andre: don't know if this is the right place */
-	} else {
-		*var = fb_display[con].var;
-	}
-
-	DPRINTK("EXIT\n");
-	return(error);
-}
-
-
-static void cyberfb_set_disp(int con, struct fb_info *info)
-{
-	struct fb_fix_screeninfo fix;
-	struct display *display;
-
-	DPRINTK("ENTER\n");
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &disp;	/* used during initialization */
-
-	cyberfb_get_fix(&fix, con, info);
-	if (con == -1)
-		con = 0;
-	display->visual = fix.visual;
-	display->type = fix.type;
-	display->type_aux = fix.type_aux;
-	display->ypanstep = fix.ypanstep;
-	display->ywrapstep = fix.ywrapstep;
-	display->can_soft_blank = 1;
-	display->inverse = Cyberfb_inverse;
-	switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-	    case 8:
-		if (display->var.accel_flags & FB_ACCELF_TEXT) {
-		    display->dispsw = &fbcon_cyber8;
-#warning FIXME: We should reinit the graphics engine here
-		} else
-		    display->dispsw = &fbcon_cfb8;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	    case 16:
-		display->dispsw = &fbcon_cfb16;
-		break;
-#endif
-	    default:
-		display->dispsw = NULL;
-		break;
-	}
-	DPRINTK("EXIT\n");
-}
-
-
-/*
- *    Set the User Defined Part of the Display
- */
-
-static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
-
-	DPRINTK("ENTER\n");
-	if ((err = do_fb_set_var(var, con == info->currcon))) {
-		DPRINTK("EXIT - do_fb_set_var failed\n");
-		return(err);
-	}
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-		oldxres = fb_display[con].var.xres;
-		oldyres = fb_display[con].var.yres;
-		oldvxres = fb_display[con].var.xres_virtual;
-		oldvyres = fb_display[con].var.yres_virtual;
-		oldbpp = fb_display[con].var.bits_per_pixel;
-		oldaccel = fb_display[con].var.accel_flags;
-		fb_display[con].var = *var;
-		if (oldxres != var->xres || oldyres != var->yres ||
-		    oldvxres != var->xres_virtual ||
-		    oldvyres != var->yres_virtual ||
-		    oldbpp != var->bits_per_pixel ||
-		    oldaccel != var->accel_flags) {
-			cyberfb_set_disp(con, info);
-			(*fb_info.changevar)(con);
-			fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
-			do_install_cmap(con, info);
-		}
-	}
-	var->activate = 0;
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-
-/*
- *    Get the Colormap
- */
-
-static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	if (con == info->currcon) { /* current console? */
-		DPRINTK("EXIT - console is current console\n");
-		return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info));
-	} else if (fb_display[con].cmap.len) { /* non default colormap? */
-		DPRINTK("Use console cmap\n");
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	} else {
-		DPRINTK("Use default cmap\n");
-		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-			     cmap, kspc ? 0 : 2);
-	}
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-static struct fb_ops cyberfb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	cyberfb_get_fix,
-	.fb_get_var =	cyberfb_get_var,
-	.fb_set_var =	cyberfb_set_var,
-	.fb_get_cmap =	cyberfb_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	cyberfb_setcolreg,
-	.fb_blank =	cyberfb_blank,
-};
-
-int __init cyberfb_setup(char *options)
-{
-	char *this_opt;
-	DPRINTK("ENTER\n");
-
-	fb_info.fontname[0] = '\0';
-
-	if (!options || !*options) {
-		DPRINTK("EXIT - no options\n");
-		return 0;
-	}
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "inverse")) {
-			Cyberfb_inverse = 1;
-			fb_invert_cmaps();
-		} else if (!strncmp(this_opt, "font:", 5)) {
-			strcpy(fb_info.fontname, this_opt+5);
-		} else if (!strcmp (this_opt, "cyber8")) {
-			cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
-			cyberfb_usermode = 1;
-		} else if (!strcmp (this_opt, "cyber16")) {
-			cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
-			cyberfb_usermode = 1;
-		} else get_video_mode(this_opt);
-	}
-
-	DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
-		cyberfb_default.xres,
-		cyberfb_default.yres,
-		cyberfb_default.bits_per_pixel);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *    Initialization
- */
-
-int __init cyberfb_init(void)
-{
-	unsigned long board_addr, board_size;
-	struct cyberfb_par par;
-	struct zorro_dev *z = NULL;
-	DPRINTK("ENTER\n");
-
-	while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64, z))) {
-	    board_addr = z->resource.start;
-	    board_size = z->resource.end-z->resource.start+1;
-	    CyberMem_phys = board_addr + 0x01400000;
-	    CyberRegs_phys = CyberMem_phys + 0x00c00000;
-	    if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 Trio64"))
-		continue;
-	    if (!request_mem_region(CyberMem_phys, 0x400000, "RAM")) {
-		release_mem_region(CyberRegs_phys, 0x10000);
-		continue;
-	    }
-	    DPRINTK("board_addr=%08lx\n", board_addr);
-	    DPRINTK("board_size=%08lx\n", board_size);
-
-	    CyberBase = ioremap(board_addr, board_size);
-	    CyberRegs = CyberBase + 0x02000000;
-	    CyberMem = CyberBase + 0x01400000;
-	    DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
-		    CyberBase, (long unsigned int)CyberRegs, CyberMem);
-
-#ifdef CYBERFBDEBUG
-	    DPRINTK("Register state just after mapping memory\n");
-	    cv64_dump();
-#endif
-
-	    strcpy(fb_info.modename, cyberfb_name);
-	    fb_info.changevar = NULL;
-	    fb_info.fbops = &cyberfb_ops;
-	    fb_info.screen_base = (unsigned char *)CyberMem;
-	    fb_info.disp = &disp;
-	    fb_info.currcon = -1;
-	    fb_info.switch_con = &Cyberfb_switch;
-	    fb_info.updatevar = &Cyberfb_updatevar;
-
-	    Cyber_init();
-	    /* ++Andre: set cyberfb default mode */
-	    if (!cyberfb_usermode) {
-		    cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
-		    DPRINTK("Use default cyber8 mode\n");
-	    }
-	    Cyber_decode_var(&cyberfb_default, &par);
-	    Cyber_encode_var(&cyberfb_default, &par);
-
-	    do_fb_set_var(&cyberfb_default, 1);
-	    cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
-	    cyberfb_set_disp(-1, &fb_info);
-	    do_install_cmap(0, &fb_info);
-
-	    if (register_framebuffer(&fb_info) < 0) {
-		    DPRINTK("EXIT - register_framebuffer failed\n");
-			if (CyberBase)
-				iounmap(CyberBase);
-		    release_mem_region(CyberMem_phys, 0x400000);
-		    release_mem_region(CyberRegs_phys, 0x10000);
-		    return -EINVAL;
-	    }
-
-	    printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
-		   fb_info.node, fb_info.modename, CyberSize>>10);
-
-	    /* TODO: This driver cannot be unloaded yet */
-	    DPRINTK("EXIT\n");
-	    return 0;
-	}
-	return -ENXIO;
-}
-
-
-static int Cyberfb_switch(int con, struct fb_info *info)
-{
-        DPRINTK("ENTER\n");
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len) {
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1, Cyber_getcolreg,
-			    info);
-	}
-
-	do_fb_set_var(&fb_display[con].var, 1);
-	info->currcon = con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	DPRINTK("EXIT\n");
-	return(0);
-}
-
-
-/*
- *    Update the `var' structure (called by fbcon.c)
- *
- *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
- *    Since it's called by a kernel driver, no range checking is done.
- */
-
-static int Cyberfb_updatevar(int con, struct fb_info *info)
-{
-	DPRINTK("Enter - Exit\n");
-	return(0);
-}
-
-
-/*
- *    Get a Video Mode
- */
-
-static int __init get_video_mode(const char *name)
-{
-	int i;
-
-	DPRINTK("ENTER\n");
-	for (i = 0; i < NUM_TOTAL_MODES; i++) {
-		if (!strcmp(name, cyberfb_predefined[i].name)) {
-			cyberfb_default = cyberfb_predefined[i].var;
-			cyberfb_usermode = 1;
-			DPRINTK("EXIT - Matched predefined mode\n");
-			return(i);
-		}
-	}
-	return(0);
-}
-
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy,
-			       int dx, int height, int width)
-{
-	DPRINTK("ENTER\n");
-	sx *= 8; dx *= 8; width *= 8;
-	Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-		     (u_short)(dy*fontheight(p)), (u_short)width,
-		     (u_short)(height*fontheight(p)), (u_short)S3_NEW);
-	DPRINTK("EXIT\n");
-}
-
-static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
-			       int sx, int height, int width)
-{
-	unsigned char bg;
-
-	DPRINTK("ENTER\n");
-	sx *= 8; width *= 8;
-	bg = attr_bgcol_ec(p,conp);
-	Cyber_RectFill((u_short)sx,
-		       (u_short)(sy*fontheight(p)),
-		       (u_short)width,
-		       (u_short)(height*fontheight(p)),
-		       (u_short)S3_NEW,
-		       (u_short)bg);
-	DPRINTK("EXIT\n");
-}
-
-static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
-			      int yy, int xx)
-{
-	DPRINTK("ENTER\n");
-	Cyber_WaitBlit();
-	fbcon_cfb8_putc(conp, p, c, yy, xx);
-	DPRINTK("EXIT\n");
-}
-
-static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
-			       const unsigned short *s, int count,
-			       int yy, int xx)
-{
-	DPRINTK("ENTER\n");
-	Cyber_WaitBlit();
-	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
-	DPRINTK("EXIT\n");
-}
-
-static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
-{
-	DPRINTK("ENTER\n");
-	Cyber_WaitBlit();
-	fbcon_cfb8_revc(p, xx, yy);
-	DPRINTK("EXIT\n");
-}
-
-static struct display_switch fbcon_cyber8 = {
-	.setup =	fbcon_cfb8_setup,
-	.bmove =	fbcon_cyber8_bmove,
-	.clear =	fbcon_cyber8_clear,
-	.putc =		fbcon_cyber8_putc,
-	.putcs =	fbcon_cyber8_putcs,
-	.revc =		fbcon_cyber8_revc,
-	.clear_margins =fbcon_cfb8_clear_margins,
-	.fontwidthmask =FONTWIDTH(8)
-};
-#endif
-
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return cyberfb_init();
-}
-#endif /* MODULE */
-
-/*
- *
- * Low level initialization routines for the CyberVision64 graphics card
- *
- * Most of the following code is from cvision_core.c
- *
- */
-
-#define MAXPIXELCLOCK 135000000 /* safety */
-
-#ifdef CV_AGGRESSIVE_TIMING
-long cv64_memclk = 55000000;
-#else
-long cv64_memclk = 50000000;
-#endif
-
-/*********************/
-
-static unsigned char clocks[]={
-  0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
-  0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
-  0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
-  0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
-  0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
-  0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
-  0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
-  0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
-  0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
-  0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
-  0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
-  0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
-  0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
-  0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
-  0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
-  0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
-  0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
-  0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
-  0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
-  0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
-  0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
-  0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
-  0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
-  0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
-  0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
-  0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
-  0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
-  0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
-  0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
-  0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
-  0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
-  0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
-  0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
-  0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
-  0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
-  0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
-  0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
-  0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
-  0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
-  0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
-  0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
-  0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
-  0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
-  0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
-  0x13, 0x1,  0x13, 0x1,  0x7d, 0x27, 0x4c, 0x9,
-  0x37, 0x22, 0x5b, 0xb,  0x71, 0x26, 0x5c, 0xb,
-  0x6b, 0xd,  0x47, 0x23, 0x14, 0x1,  0x4f, 0x9,
-  0x23, 0x3,  0x75, 0x26, 0x7d, 0xf,  0x1c, 0x2,
-  0x51, 0x9,  0x59, 0x24, 0x61, 0xb,  0x69, 0x25,
-  0x79, 0x26, 0x34, 0x5,  0x1d, 0x2,  0x6b, 0x25,
-  0x54, 0x9,  0x35, 0x5,  0x45, 0x7,  0x6d, 0x25,
-  0x7d, 0x26, 0x16, 0x1,  0x7f, 0x26, 0x77, 0xd,
-  0x4f, 0x23, 0x78, 0xd,  0x2f, 0x21, 0x27, 0x3,
-  0x1f, 0x2,  0x59, 0x9,  0x6a, 0xb,  0x73, 0x25,
-  0x6b, 0xb,  0x63, 0x24, 0x5b, 0x9,  0x20, 0x2,
-  0x7e, 0xd,  0x4b, 0x7,  0x65, 0x24, 0x43, 0x22,
-  0x18, 0x1,  0x6f, 0xb,  0x5e, 0x9,  0x70, 0xb,
-  0x2a, 0x3,  0x33, 0x4,  0x45, 0x6,  0x60, 0x9,
-  0x7b, 0xc,  0x19, 0x1,  0x19, 0x1,  0x7d, 0xc,
-  0x74, 0xb,  0x50, 0x7,  0x75, 0xb,  0x63, 0x9,
-  0x51, 0x7,  0x23, 0x2,  0x3f, 0x5,  0x1a, 0x1,
-  0x65, 0x9,  0x2d, 0x3,  0x40, 0x5,  0x0,  0x0,
-};
-
-/* Console colors */
-unsigned char cvconscolors[16][3] = {	/* background, foreground, hilite */
-  /*  R     G     B  */
-  {0x30, 0x30, 0x30},
-  {0x00, 0x00, 0x00},
-  {0x80, 0x00, 0x00},
-  {0x00, 0x80, 0x00},
-  {0x00, 0x00, 0x80},
-  {0x80, 0x80, 0x00},
-  {0x00, 0x80, 0x80},
-  {0x80, 0x00, 0x80},
-  {0xff, 0xff, 0xff},
-  {0x40, 0x40, 0x40},
-  {0xff, 0x00, 0x00},
-  {0x00, 0xff, 0x00},
-  {0x00, 0x00, 0xff},
-  {0xff, 0xff, 0x00},
-  {0x00, 0xff, 0xff},
-  {0x00, 0x00, 0xff}
-};
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-/* Read Attribute Controller Register=idx */
-inline unsigned char RAttr (volatile unsigned char *regs, short idx)
-{
-	wb_64 (regs, ACT_ADDRESS_W, idx);
-	mb();
-	udelay(100);
-	return (rb_64(regs, ACT_ADDRESS_R));
-}
-
-/* Read Sequencer Register=idx */
-inline unsigned char RSeq (volatile unsigned char *regs, short idx)
-{
-	wb_64 (regs, SEQ_ADDRESS, idx);
-	mb();
-	return (rb_64(regs, SEQ_ADDRESS_R));
-}
-
-/* Read CRT Controller Register=idx */
-inline unsigned char RCrt (volatile unsigned char *regs, short idx)
-{
-	wb_64 (regs, CRT_ADDRESS, idx);
-	mb();
-	return (rb_64(regs, CRT_ADDRESS_R));
-}
-
-/* Read Graphics Controller Register=idx */
-inline unsigned char RGfx (volatile unsigned char *regs, short idx)
-{
-	wb_64 (regs, GCT_ADDRESS, idx);
-	mb();
-	return (rb_64(regs, GCT_ADDRESS_R));
-}
-
-/*
- * Special wakeup/passthrough registers on graphics boards
- */
-
-inline void cv64_write_port (unsigned short bits,
-			     volatile unsigned char *base)
-{
-	volatile unsigned char *addr;
-	static unsigned char cvportbits = 0; /* Mirror port bits here */
-	DPRINTK("ENTER\n");
-
-	addr = base + 0x40001;
-	if (bits & 0x8000) {
-		cvportbits |= bits & 0xff; /* Set bits */
-		DPRINTK("Set bits: %04x\n", bits);
-	} else {
-		bits = bits & 0xff;
-		bits = (~bits) & 0xff;
-		cvportbits &= bits; /* Clear bits */
-		DPRINTK("Clear bits: %04x\n", bits);
-	}
-
-	*addr = cvportbits;
-	DPRINTK("EXIT\n");
-}
-
-/*
- * Monitor switch on CyberVision board
- *
- *  toggle:
- *    0 = CyberVision Signal
- *    1 = Amiga Signal
- *  board = board addr
- *
- */
-inline void cvscreen (int toggle, volatile unsigned char *board)
-{
-	DPRINTK("ENTER\n");
-	if (toggle == 1) {
-		DPRINTK("Show Amiga video\n");
-		cv64_write_port (0x10, board);
-	} else {
-		DPRINTK("Show CyberVision video\n");
-		cv64_write_port (0x8010, board);
-	}
-	DPRINTK("EXIT\n");
-}
-
-/* Control screen display */
-/* toggle: 0 = on, 1 = off */
-/* board = registerbase */
-inline void gfx_on_off(int toggle, volatile unsigned char *regs)
-{
-	int r;
-	DPRINTK("ENTER\n");
-	
-	toggle &= 0x1;
-	toggle = toggle << 5;
-	DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
-	
-	r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
-	r &= 0xdf;	/* Set bit 5 to 0 */
-	
-	WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
-	DPRINTK("EXIT\n");
-}
-
-/*
- * Computes M, N, and R values from
- * given input frequency. It uses a table of
- * precomputed values, to keep CPU time low.
- *
- * The return value consist of:
- * lower byte:  Bits 4-0: N Divider Value
- *	        Bits 5-6: R Value          for e.g. SR10 or SR12
- * higher byte: Bits 0-6: M divider value  for e.g. SR11 or SR13
- */
-static unsigned short cv64_compute_clock(unsigned long freq)
-{
-	static unsigned char *mnr, *save;	/* M, N + R vals */
-	unsigned long work_freq, r;
-	unsigned short erg;
-	long diff, d2;
-
-	DPRINTK("ENTER\n");
-	if (freq < 12500000 || freq > MAXPIXELCLOCK) {
-		printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
-		       freq);
-		freq = 25000000;
-	}
-	DPRINTK("Freq = %ld\n", freq);
-	mnr = clocks;	/* there the vals are stored */
-	d2 = 0x7fffffff;
-
-	while (*mnr) {	/* mnr vals are 0-terminated */
-		work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
-
-		r = (mnr[1] >> 5) & 0x03;
-		if (r != 0) {
-			work_freq = work_freq >> r;	/* r is the freq divider */
-		}
-
-		work_freq *= 0x3E8;	/* 2nd part of OSC */
-
-		diff = abs(freq - work_freq);
-
-		if (d2 >= diff) {
-			d2 = diff;
-			/* In save are the vals for minimal diff */
-			save = mnr;
-		}
-		mnr += 2;
-	}
-	erg = *((unsigned short *)save);
-
-	DPRINTK("EXIT\n");
-	return (erg);
-}
-
-static int cv_has_4mb (volatile unsigned char *fb)
-{
-	volatile unsigned long *tr, *tw;
-	DPRINTK("ENTER\n");
-
-	/* write patterns in memory and test if they can be read */
-	tw = (volatile unsigned long *) fb;
-	tr = (volatile unsigned long *) (fb + 0x02000000);
-
-	*tw = 0x87654321;
-	
-	if (*tr != 0x87654321) {
-		DPRINTK("EXIT - <4MB\n");
-		return (0);
-	}
-
-	/* upper memory region */
-	tw = (volatile unsigned long *) (fb + 0x00200000);
-	tr = (volatile unsigned long *) (fb + 0x02200000);
-
-	*tw = 0x87654321;
-
-	if (*tr != 0x87654321) {
-		DPRINTK("EXIT - <4MB\n");
-		return (0);
-	}
-
-	*tw = 0xAAAAAAAA;
-
-	if (*tr != 0xAAAAAAAA) {
-		DPRINTK("EXIT - <4MB\n");
-		return (0);
-	}
-
-	*tw = 0x55555555;
-
-	if (*tr != 0x55555555) {
-		DPRINTK("EXIT - <4MB\n");
-		return (0);
-	}
-
-	DPRINTK("EXIT\n");
-	return (1);
-}
-
-static void cv64_board_init (void)
-{
-	volatile unsigned char *regs = CyberRegs;
-	int i;
-	unsigned int clockpar;
-	unsigned char test;
-	
-	DPRINTK("ENTER\n");
-
-	/*
-	 * Special CyberVision 64 board operations
-	 */
-	/* Reset board */
-	for (i = 0; i < 6; i++) {
-		cv64_write_port (0xff, CyberBase);
-	}
-	/* Return to operational mode */
-	cv64_write_port (0x8004, CyberBase);
-	
-	/*
-	 * Generic (?) S3 chip wakeup
-	 */
-	/* Disable I/O & memory decoders, video in setup mode */
-	wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
-	/* Video responds to cmds, addrs & data */
-	wb_64 (regs, SREG_OPTION_SELECT, 0x1);
-	/* Enable I/O & memory decoders, video in operational mode */
-	wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
-	/* VGA color emulation, enable cpu access to display mem */ 
-	wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
-	/* Unlock S3 VGA regs */
-	WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48); 
-	/* Unlock system control & extension registers */
-	WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
-/* GRF - Enable interrupts */
-	/* Enable enhanced regs access, Ready cntl 0 wait states */
-	test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
-	test = test | 0x01;		/* enable enhanced register access */
-	test = test & 0xEF;		/* clear bit 4, 0 wait state */
-	WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
-	/*
-	 * bit 0=1: Enable enhaced mode functions
-	 * bit 2=0: Enhanced mode 8+ bits/pixel
-	 * bit 4=1: Enable linear addressing
-	 * bit 5=1: Enable MMIO
-	 */
-	wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
-	/*
-	 * bit 0=1: Color emulation
-	 * bit 1=1: Enable CPU access to display memory
-	 * bit 5=1: Select high 64K memory page
-	 */
-/* GRF - 0xE3 */
-	wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
-	
-	/* Cpu base addr */
-	WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
-	
-	/* Reset. This does nothing on Trio, but standard VGA practice */
-	/* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
-	/* Character clocks 8 dots wide */
-	WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
-	/* Enable cpu write to all color planes */
-	WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
-	/* Font table in 1st 8k of plane 2, font A=B disables swtich */
-	WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
-	/* Allow mem access to 256kb */
-	WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
-	/* Unlock S3 extensions to VGA Sequencer regs */
-	WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
-	
-	/* Enable 4MB fast page mode */
-	test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
-	test = test | 1 << 6;
-	WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test);
-	
-	/* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
-	WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
-
-	/* Clear immediate clock load bit */
-	test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
-	test = test & 0xDF;
-	/* If > 55MHz, enable 2 cycle memory write */
-	if (cv64_memclk >= 55000000) {
-		test |= 0x80;
-	}
-	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
-
-	/* Set MCLK value */
-	clockpar = cv64_compute_clock (cv64_memclk);
-	test = (clockpar & 0xFF00) >> 8;
-	WSeq (regs, SEQ_ID_MCLK_HI, test);
-	test = clockpar & 0xFF;
-	WSeq (regs, SEQ_ID_MCLK_LO, test);
-
-	/* Chip rev specific: Not in my Trio manual!!! */
-	if (RCrt (regs, CRT_ID_REVISION) == 0x10)
-		WSeq (regs, SEQ_ID_MORE_MAGIC, test);
-
-	/* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
-
-	/* Set DCLK value */
-	WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
-	WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
-
-	/* Load DCLK (and MCLK?) immediately */
-	test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
-	test = test | 0x22;
-	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
-
-	/* Enable loading of DCLK */
-	test = rb_64(regs, GREG_MISC_OUTPUT_R);
-	test = test | 0x0C;
-	wb_64 (regs, GREG_MISC_OUTPUT_W, test);
-
-	/* Turn off immediate xCLK load */
-	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
-
-	/* Horizontal character clock counts */
-	/* 8 LSB of 9 bits = total line - 5 */
-	WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
-	/* Active display line */
-	WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
-	/* Blank assertion start */
-	WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
-	/* Blank assertion end */
-	WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
-	/* HSYNC assertion start */
-	WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
-	/* HSYNC assertion end */
-	WCrt (regs, CRT_ID_END_HOR_RETR, 0x80);
-	WCrt (regs, CRT_ID_VER_TOTAL, 0xBF);
-	WCrt (regs, CRT_ID_OVERFLOW, 0x1F);
-	WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
-	WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40);
-	WCrt (regs, CRT_ID_CURSOR_START, 0x00);
-	WCrt (regs, CRT_ID_CURSOR_END, 0x00);
-	WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
-	WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
-	WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
-	WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
-	WCrt (regs, CRT_ID_START_VER_RETR, 0x9C);
-	WCrt (regs, CRT_ID_END_VER_RETR, 0x0E);
-	WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
-	WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50);
-	WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00);
-	WCrt (regs, CRT_ID_START_VER_BLANK, 0x96);
-	WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9);
-	WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
-	WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
-	WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10);	/* FIFO enabled */
-	WCrt (regs, CRT_ID_MISC_1, 0x35);
-	WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A);
-	WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
-	WCrt (regs, CRT_ID_LAW_POS_LO, 0x40);
-	WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
-
-	WGfx (regs, GCT_ID_SET_RESET, 0x0);
-	WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0);
-	WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0);
-	WGfx (regs, GCT_ID_DATA_ROTATE, 0x0);
-	WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0);
-	WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40);
-	WGfx (regs, GCT_ID_MISC, 0x01);
-	WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F);
-	WGfx (regs, GCT_ID_BITMASK, 0xFF);
-
-	/* Colors for text mode */
-	for (i = 0; i < 0xf; i++)
-		WAttr (regs, i, i);
-
-	WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
-	WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01);
-	WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
-	WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0);
-	WAttr (regs, ACT_ID_COLOR_SELECT, 0x0);
-
-	wb_64 (regs, VDAC_MASK, 0xFF);
-
-	*((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
-	*((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
-
-	/* Colors initially set to grayscale */
-
-	wb_64 (regs, VDAC_ADDRESS_W, 0);
-	for (i = 255; i >= 0; i--) {
-		wb_64(regs, VDAC_DATA, i);
-		wb_64(regs, VDAC_DATA, i);
-		wb_64(regs, VDAC_DATA, i);
-	}
-
-	/* GFx hardware cursor off */
-	WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
-
-	/* Set first to 4MB, so test will work */
-	WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
-	/* Find "correct" size of fbmem of Z3 board */
-	if (cv_has_4mb (CyberMem)) {
-		CyberSize = 1024 * 1024 * 4;
-		WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
-		DPRINTK("4MB board\n");
-	} else {
-		CyberSize = 1024 * 1024 * 2;
-		WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
-		DPRINTK("2MB board\n");
-	}
-
-	/* Initialize graphics engine */
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_FRGD_MIX, 0x27);
-	vgaw16 (regs, ECR_BKGD_MIX, 0x07);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
-	udelay(200);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
-	Cyber_WaitBlit();
-	udelay(200);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_READ_REG_DATA, 0xE000);
-	vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00);
-	vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
-	vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00);
-	vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00);
-	vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00);
-	vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00);
-	vgaw16 (regs, ECR_SHORT_STROKE, 0x00);
-	vgaw16 (regs, ECR_DRAW_CMD, 0x01);
-
-	Cyber_WaitBlit();
-
-	vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
-	vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
-	vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
-
-
-	/* Enable video display (set bit 5) */
-/* ARB - Would also seem to write to AR13.
- *       May want to use parts of WAttr to set JUST bit 5
- */
-	WAttr (regs, 0x33, 0);
-	
-/* GRF - function code ended here */
-
-	/* Turn gfx on again */
-	gfx_on_off (0, regs);
-
-	/* Pass-through */
-	cvscreen (0, CyberBase);
-
-	DPRINTK("EXIT\n");
-}
-
-static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
-{
-  volatile unsigned char *regs = CyberRegs;
-  int fx, fy;
-  unsigned short mnr;
-  unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
-  char LACE, DBLSCAN, TEXT, CONSOLE;
-  int cr50, sr15, sr18, clock_mode, test;
-  int m, n;
-  int tfillm, temptym;
-  int hmul;
-	
-  /* ---------------- */
-  int xres, hfront, hsync, hback;
-  int yres, vfront, vsync, vback;
-  int bpp;
-#if 0
-  float freq_f;
-#endif
-  long freq;
-  /* ---------------- */
-	
-  DPRINTK("ENTER\n");
-  TEXT = 0;	/* if depth == 4 */
-  CONSOLE = 0;	/* mode num == 255 (console) */
-  fx = fy = 8;	/* force 8x8 font */
-
-/* GRF - Disable interrupts */	
-	
-  gfx_on_off (1, regs);
-	
-  switch (video_mode->bits_per_pixel) {
-  case 15:
-  case 16:
-    hmul = 2;
-    break;
-		
-  default:
-    hmul = 1;
-    break;
-  }
-	
-  bpp = video_mode->bits_per_pixel;
-  xres = video_mode->xres;
-  hfront = video_mode->right_margin;
-  hsync = video_mode->hsync_len;
-  hback = video_mode->left_margin;
-
-  LACE = 0;
-  DBLSCAN = 0;
-
-  if (video_mode->vmode & FB_VMODE_DOUBLE) {
-    yres = video_mode->yres * 2;
-    vfront = video_mode->lower_margin * 2;
-    vsync = video_mode->vsync_len * 2;
-    vback = video_mode->upper_margin * 2;
-    DBLSCAN = 1;
-  } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
-    yres = (video_mode->yres + 1) / 2;
-    vfront = (video_mode->lower_margin + 1) / 2;
-    vsync = (video_mode->vsync_len + 1) / 2;
-    vback = (video_mode->upper_margin + 1) / 2;
-    LACE = 1;
-  } else {
-    yres = video_mode->yres;
-    vfront = video_mode->lower_margin;
-    vsync = video_mode->vsync_len;
-    vback = video_mode->upper_margin;
-  }
-
-  /* ARB Dropping custom setup method from cvision.c */
-#if 0
-  if (cvision_custom_mode) {
-    HBS = hbs / 8 * hmul;
-    HBE = hbe / 8 * hmul;
-    HSS = hss / 8 * hmul;
-    HSE = hse / 8 * hmul;
-    HT  = ht / 8 * hmul - 5;
-		
-    VBS = vbs - 1;
-    VSS = vss;
-    VSE = vse;
-    VBE = vbe;
-    VT  = vt - 2;
-  } else {
-#else
-    {
-#endif
-    HBS = hmul * (xres / 8);
-    HBE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8) - 2);
-    HSS = hmul * ((xres/8) + (hfront/8) + 2);
-    HSE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + 1);
-    HT  = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8));
-	
-    VBS = yres;
-    VBE = yres + vfront + vsync + vback - 2;
-    VSS = yres + vfront - 1;
-    VSE = yres + vfront + vsync - 1;
-    VT  = yres + vfront + vsync + vback - 2;
-  }
-
-  wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
-	
-  if (TEXT)
-    HDE = ((video_mode->xres + fx - 1) / fx) - 1;
-  else
-    HDE = (video_mode->xres + 3) * hmul / 8 - 1;
-	
-  VDE = video_mode->yres - 1;
-
-  WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
-  WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
-	
-  WSeq (regs, SEQ_ID_MEMORY_MODE,
-	(TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
-  WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00);
-  WSeq (regs, SEQ_ID_MAP_MASK,
-	(video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
-  WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
-	
-  /* cv64_compute_clock accepts arguments in Hz */
-  /* pixclock is in ps ... convert to Hz */
-	
-#if 0
-  freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
-  freq = ((long) freq_f) * 1000;
-#else
-/* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
- */
-  freq = (1000000000 / video_mode->pixclock) * 1000;
-#endif
-
-  mnr = cv64_compute_clock (freq);
-  WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
-  WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
-	
-  /* Load display parameters into board */
-  WCrt (regs, CRT_ID_EXT_HOR_OVF,
-	((HT & 0x100) ? 0x01 : 0x00) |
-	((HDE & 0x100) ? 0x02 : 0x00) |
-	((HBS & 0x100) ? 0x04 : 0x00) |
-	/* ((HBE & 0x40) ? 0x08 : 0x00) | */
-	((HSS & 0x100) ? 0x10 : 0x00) |
-	/* ((HSE & 0x20) ? 0x20 : 0x00) | */
-	(((HT-5) & 0x100) ? 0x40 : 0x00)
-	);
-	
-  WCrt (regs, CRT_ID_EXT_VER_OVF,
-	0x40 |
-	((VT & 0x400) ? 0x01 : 0x00) |
-	((VDE & 0x400) ? 0x02 : 0x00) |
-	((VBS & 0x400) ? 0x04 : 0x00) |
-	((VSS & 0x400) ? 0x10 : 0x00)
-	);
-	
-  WCrt (regs, CRT_ID_HOR_TOTAL, HT);
-  WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5);
-  WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
-  WCrt (regs, CRT_ID_START_HOR_BLANK, HBS);
-  WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
-  WCrt (regs, CRT_ID_START_HOR_RETR, HSS);
-  WCrt (regs, CRT_ID_END_HOR_RETR,
-	(HSE & 0x1F) |
-	((HBE & 0x20) ? 0x80 : 0x00)
-	);
-  WCrt (regs, CRT_ID_VER_TOTAL, VT);
-  WCrt (regs, CRT_ID_OVERFLOW,
-	0x10 |
-	((VT & 0x100) ? 0x01 : 0x00) |
-	((VDE & 0x100) ? 0x02 : 0x00) |
-	((VSS & 0x100) ? 0x04 : 0x00) |
-	((VBS & 0x100) ? 0x08 : 0x00) |
-	((VT & 0x200) ? 0x20 : 0x00) |
-	((VDE & 0x200) ? 0x40 : 0x00) |
-	((VSS & 0x200) ? 0x80 : 0x00)
-	);
-  WCrt (regs, CRT_ID_MAX_SCAN_LINE,
-	0x40 |
-	(DBLSCAN ? 0x80 : 0x00) |
-	((VBS & 0x200) ? 0x20 : 0x00) |
-	(TEXT ? ((fy - 1) & 0x1F) : 0x00)
-	);
-	
-  WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
-
-  /* Text cursor */
-	
-  if (TEXT) {
-#if 1
-    WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
-    WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
-#else
-    WCrt (regs, CRT_ID_CURSOR_START, 0x00);
-    WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
-#endif
-    WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
-    WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
-    WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
-  }
-	
-  WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
-  WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
-  WCrt (regs, CRT_ID_START_VER_RETR, VSS);
-  WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
-  WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE);
-  WCrt (regs, CRT_ID_START_VER_BLANK, VBS);
-  WCrt (regs, CRT_ID_END_VER_BLANK, VBE);
-  WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
-  WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2);
-  WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
-  WGfx (regs, GCT_ID_GRAPHICS_MODE,
-	((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
-  WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
-  WSeq (regs, SEQ_ID_MEMORY_MODE,
-	((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
-	
-  wb_64 (regs, VDAC_MASK, 0xFF);
-	
-  /* Blank border */
-  test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
-  WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
-	
-  sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
-  sr15 &= 0xEF;
-  sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
-  sr18 &= 0x7F;
-  clock_mode = 0x00;
-  cr50 = 0x00;
-	
-  test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
-  test &= 0xD;
-	
-  /* Clear roxxler byte-swapping... */
-  cv64_write_port (0x0040, CyberBase);
-  cv64_write_port (0x0020, CyberBase);
-	
-  switch (video_mode->bits_per_pixel) {
-  case 1:
-  case 4:	/* text */
-    HDE = video_mode->xres / 16;
-    break;
-		
-  case 8:
-    if (freq > 80000000) {
-      clock_mode = 0x10 | 0x02;
-      sr15 |= 0x10;
-      sr18 |= 0x80;
-    }
-    HDE = video_mode->xres / 8;
-    cr50 |= 0x00;
-    break;
-		
-  case 15:
-    cv64_write_port (0x8020, CyberBase);
-    clock_mode = 0x30;
-    HDE = video_mode->xres / 4;
-    cr50 |= 0x10;
-    break;
-		
-  case 16:
-    cv64_write_port (0x8020, CyberBase);
-    clock_mode = 0x50;
-    HDE = video_mode->xres / 4;
-    cr50 |= 0x10;
-    break;
-		
-  case 24:
-  case 32:
-    cv64_write_port (0x8040, CyberBase);
-    clock_mode = 0xD0;
-    HDE = video_mode->xres / 2;
-    cr50 |= 0x30;
-    break;
-  }
-
-  WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
-  WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
-  WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18);
-  WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE);
-
-  WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
-	
-  test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
-  test &= ~0x30;
-  test |= (HDE >> 4) & 0x30;
-  WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
-	
-  /* Set up graphics engine */
-  switch (video_mode->xres) {
-  case 1024:
-    cr50 |= 0x00;
-    break;
-		
-  case 640:
-    cr50 |= 0x40;
-    break;
-		
-  case 800:
-    cr50 |= 0x80;
-    break;
-		
-  case 1280:
-    cr50 |= 0xC0;
-    break;
-		
-  case 1152:
-    cr50 |= 0x01;
-    break;
-		
-  case 1600:
-    cr50 |= 0x81;
-    break;
-		
-  default:	/* XXX */
-    break;
-  }
-	
-  WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
-	
-  udelay(100);
-  WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
-  udelay(100);
-  WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
-	 (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
-  udelay(100);
-	
-  tfillm = (96 * (cv64_memclk / 1000)) / 240000;
-	
-  switch (video_mode->bits_per_pixel) {
-  case 32:
-  case 24:
-    temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
-    break;
-  case 15:
-  case 16:
-    temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
-    break;
-  case 4:
-    temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
-    break;
-  default:
-    temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
-    break;
-  }
-	
-  m = (temptym - tfillm - 9) / 2;
-  if (m < 0)
-    m = 0;
-  m = (m & 0x1F) << 3;
-  if (m < 0x18)
-    m = 0x18;
-  n = 0xFF;
-	
-  WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
-  WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
-  udelay(10);
-	
-  /* Text initialization */
-	
-  if (TEXT) {
-    /* Do text initialization here ! */
-  }
-	
-  if (CONSOLE) {
-    int i;
-    wb_64 (regs, VDAC_ADDRESS_W, 0);
-    for (i = 0; i < 4; i++) {
-      wb_64 (regs, VDAC_DATA, cvconscolors [i][0]);
-      wb_64 (regs, VDAC_DATA, cvconscolors [i][1]);
-      wb_64 (regs, VDAC_DATA, cvconscolors [i][2]);
-    }
-  }
-	
-  WAttr (regs, 0x33, 0);
-	
-  /* Turn gfx on again */
-  gfx_on_off (0, (volatile unsigned char *) regs);
-	
-  /* Pass-through */
-  cvscreen (0, CyberBase);
-
-DPRINTK("EXIT\n");
-}
-
-void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
-		     u_short w, u_short h)
-{
-	volatile unsigned char *regs = CyberRegs;
-	unsigned short drawdir = 0;
-	
-	DPRINTK("ENTER\n");
-	if (sx > dx) {
-		drawdir |= 1 << 5;
-	} else {
-		sx += w - 1;
-		dx += w - 1;
-	}
-	
-	if (sy > dy) {
-		drawdir |= 1 << 7;
-	} else {
-		sy += h - 1;
-		dy += h - 1;
-	}
-	
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
-	vgaw16 (regs, ECR_BKGD_MIX, 0x7);
-	vgaw16 (regs, ECR_FRGD_MIX, 0x67);
-	vgaw16 (regs, ECR_BKGD_COLOR, 0x0);
-	vgaw16 (regs, ECR_FRGD_COLOR, 0x1);
-	vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1);
-	vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
-	vgaw16 (regs, ECR_CURRENT_Y_POS, sy);
-	vgaw16 (regs, ECR_CURRENT_X_POS, sx);
-	vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy);
-	vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx);
-	vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
-	vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
-	vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir);
-	DPRINTK("EXIT\n");
-}
-
-void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
-{
-	volatile unsigned char *regs = CyberRegs;
-	DPRINTK("ENTER\n");
-	Cyber_WaitBlit();
-	vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
-	vgaw16 (regs, ECR_FRGD_COLOR, bg);
-	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
-	vgaw16 (regs, ECR_CURRENT_Y_POS, dy);
-	vgaw16 (regs, ECR_CURRENT_X_POS, dx);
-	vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
-	vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
-	vgaw16 (regs, ECR_DRAW_CMD, 0x40B1);	
-	DPRINTK("EXIT\n");
-}
-
-#ifdef CYBERFBDEBUG
-/*
- * Dump internal settings of CyberVision board
- */
-static void cv64_dump (void)
-{
-	volatile unsigned char *regs = CyberRegs;
-	DPRINTK("ENTER\n");
-        /* Dump the VGA setup values */
-	*(regs + S3_CRTC_ADR) = 0x00;
-	DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x01;
-	DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x02;
-	DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x03;
-	DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x04;
-	DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x05;
-	DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x06;
-	DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x07;
-	DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x08;
-	DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x09;
-	DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x10;
-	DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x11;
-	DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x12;
-	DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x13;
-	DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x15;
-	DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x16;
-	DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x36;
-	DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x37;
-	DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x42;
-	DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x43;
-	DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x50;
-	DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x51;
-	DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x53;
-	DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x58;
-	DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x59;
-	DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x5A;
-	DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x5D;
-	DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x5E;
-	DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
-	DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
-	*(regs + SEQ_ADDRESS) = 0x01;
-	DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x02;
-	DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x03;
-	DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x09;
-	DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x10;
-	DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x11;
-	DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x12;
-	DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x13;
-	DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x15;
-	DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));
-	
-	return;
-}
-#endif
diff --git a/drivers/video/cyberfb.h b/drivers/video/cyberfb.h
deleted file mode 100644
index 8435c43..0000000
--- a/drivers/video/cyberfb.h
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * linux/arch/m68k/console/cvision.h -- CyberVision64 definitions for the
- *                                      text console driver.
- *
- *   Copyright (c) 1998 Alan Bair
- *
- * This file is based on the initial port to Linux of grf_cvreg.h:
- *
- *   Copyright (c) 1997 Antonio Santos
- *
- * The original work is from the NetBSD CyberVision 64 framebuffer driver 
- * and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
- * Permission to use the source of this driver was obtained from the
- * author Michael Teske by Alan Bair.
- *
- *   Copyright (c) 1995 Michael Teske
- *
- * History:
- *
- *
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/* s3 commands */
-#define S3_BITBLT       0xc011
-#define S3_TWOPOINTLINE 0x2811
-#define S3_FILLEDRECT   0x40b1
-
-#define S3_FIFO_EMPTY 0x0400
-#define S3_HDW_BUSY   0x0200
-
-/* Enhanced register mapping (MMIO mode) */
-
-#define S3_READ_SEL      0xbee8 /* offset f */
-#define S3_MULT_MISC     0xbee8 /* offset e */
-#define S3_ERR_TERM      0x92e8
-#define S3_FRGD_COLOR    0xa6e8
-#define S3_BKGD_COLOR    0xa2e8
-#define S3_PIXEL_CNTL    0xbee8 /* offset a */
-#define S3_FRGD_MIX      0xbae8
-#define S3_BKGD_MIX      0xb6e8
-#define S3_CUR_Y         0x82e8
-#define S3_CUR_X         0x86e8
-#define S3_DESTY_AXSTP   0x8ae8
-#define S3_DESTX_DIASTP  0x8ee8
-#define S3_MIN_AXIS_PCNT 0xbee8 /* offset 0 */
-#define S3_MAJ_AXIS_PCNT 0x96e8
-#define S3_CMD           0x9ae8
-#define S3_GP_STAT       0x9ae8
-#define S3_ADVFUNC_CNTL  0x4ae8
-#define S3_WRT_MASK      0xaae8
-#define S3_RD_MASK       0xaee8
-
-/* Enhanced register mapping (Packed MMIO mode, write only) */
-#define S3_ALT_CURXY     0x8100
-#define S3_ALT_CURXY2    0x8104
-#define S3_ALT_STEP      0x8108
-#define S3_ALT_STEP2     0x810c
-#define S3_ALT_ERR       0x8110
-#define S3_ALT_CMD       0x8118
-#define S3_ALT_MIX       0x8134
-#define S3_ALT_PCNT      0x8148
-#define S3_ALT_PAT       0x8168
-
-/* Drawing modes */
-#define S3_NOTCUR          0x0000
-#define S3_LOGICALZERO     0x0001
-#define S3_LOGICALONE      0x0002
-#define S3_LEAVEASIS       0x0003
-#define S3_NOTNEW          0x0004
-#define S3_CURXORNEW       0x0005
-#define S3_NOT_CURXORNEW   0x0006
-#define S3_NEW             0x0007
-#define S3_NOTCURORNOTNEW  0x0008
-#define S3_CURORNOTNEW     0x0009
-#define S3_NOTCURORNEW     0x000a
-#define S3_CURORNEW        0x000b
-#define S3_CURANDNEW       0x000c
-#define S3_NOTCURANDNEW    0x000d
-#define S3_CURANDNOTNEW    0x000e
-#define S3_NOTCURANDNOTNEW 0x000f
-
-#define S3_CRTC_ADR    0x03d4
-#define S3_CRTC_DATA   0x03d5
-
-#define S3_REG_LOCK2 0x39
-#define S3_HGC_MODE  0x45
-
-#define S3_HWGC_ORGX_H 0x46
-#define S3_HWGC_ORGX_L 0x47
-#define S3_HWGC_ORGY_H 0x48
-#define S3_HWGC_ORGY_L 0x49
-#define S3_HWGC_DX     0x4e
-#define S3_HWGC_DY     0x4f
-
-#define S3_LAW_CTL 0x58
-
-/**************************************************/
-
-/* support for a BitBlt operation. The op-codes are identical
-   to X11 GCs */
-#define	GRFBBOPclear		0x0	/* 0 */
-#define GRFBBOPand		0x1	/* src AND dst */
-#define GRFBBOPandReverse	0x2	/* src AND NOT dst */
-#define GRFBBOPcopy		0x3	/* src */
-#define GRFBBOPandInverted	0x4	/* NOT src AND dst */
-#define	GRFBBOPnoop		0x5	/* dst */
-#define GRFBBOPxor		0x6	/* src XOR dst */
-#define GRFBBOPor		0x7	/* src OR dst */
-#define GRFBBOPnor		0x8	/* NOT src AND NOT dst */
-#define GRFBBOPequiv		0x9	/* NOT src XOR dst */
-#define GRFBBOPinvert		0xa	/* NOT dst */
-#define GRFBBOPorReverse	0xb	/* src OR NOT dst */
-#define GRFBBOPcopyInverted	0xc	/* NOT src */
-#define GRFBBOPorInverted	0xd	/* NOT src OR dst */
-#define GRFBBOPnand		0xe	/* NOT src OR NOT dst */
-#define GRFBBOPset		0xf	/* 1 */
-
-
-/* Write 16 Bit VGA register */
-#define vgaw16(ba, reg, val) \
-*((unsigned short *)  (((volatile unsigned char *)ba)+reg)) = val
-
-/*
- * Defines for the used register addresses (mw)
- *
- * NOTE: There are some registers that have different addresses when
- *       in mono or color mode. We only support color mode, and thus
- *       some addresses won't work in mono-mode!
- *
- * General and VGA-registers taken from retina driver. Fixed a few
- * bugs in it. (SR and GR read address is Port + 1, NOT Port)
- *
- */
-
-/* General Registers: */
-#define GREG_MISC_OUTPUT_R	0x03CC
-#define GREG_MISC_OUTPUT_W	0x03C2	
-#define GREG_FEATURE_CONTROL_R	0x03CA
-#define GREG_FEATURE_CONTROL_W	0x03DA
-#define GREG_INPUT_STATUS0_R	0x03C2
-#define GREG_INPUT_STATUS1_R	0x03DA
-
-/* Setup Registers: */
-#define SREG_OPTION_SELECT	0x0102
-#define SREG_VIDEO_SUBS_ENABLE	0x46E8
-
-/* Attribute Controller: */
-#define ACT_ADDRESS		0x03C0
-#define ACT_ADDRESS_R		0x03C1
-#define ACT_ADDRESS_W		0x03C0
-#define ACT_ADDRESS_RESET	0x03DA
-#define ACT_ID_PALETTE0		0x00
-#define ACT_ID_PALETTE1		0x01
-#define ACT_ID_PALETTE2		0x02
-#define ACT_ID_PALETTE3		0x03
-#define ACT_ID_PALETTE4		0x04
-#define ACT_ID_PALETTE5		0x05
-#define ACT_ID_PALETTE6		0x06
-#define ACT_ID_PALETTE7		0x07
-#define ACT_ID_PALETTE8		0x08
-#define ACT_ID_PALETTE9		0x09
-#define ACT_ID_PALETTE10	0x0A
-#define ACT_ID_PALETTE11	0x0B
-#define ACT_ID_PALETTE12	0x0C
-#define ACT_ID_PALETTE13	0x0D
-#define ACT_ID_PALETTE14	0x0E
-#define ACT_ID_PALETTE15	0x0F
-#define ACT_ID_ATTR_MODE_CNTL	0x10
-#define ACT_ID_OVERSCAN_COLOR	0x11
-#define ACT_ID_COLOR_PLANE_ENA	0x12
-#define ACT_ID_HOR_PEL_PANNING	0x13
-#define ACT_ID_COLOR_SELECT	0x14
-
-/* Graphics Controller: */
-#define GCT_ADDRESS		0x03CE
-#define GCT_ADDRESS_R		0x03CF
-#define GCT_ADDRESS_W		0x03CF
-#define GCT_ID_SET_RESET	0x00
-#define GCT_ID_ENABLE_SET_RESET	0x01
-#define GCT_ID_COLOR_COMPARE	0x02
-#define GCT_ID_DATA_ROTATE	0x03
-#define GCT_ID_READ_MAP_SELECT	0x04
-#define GCT_ID_GRAPHICS_MODE	0x05
-#define GCT_ID_MISC		0x06
-#define GCT_ID_COLOR_XCARE	0x07
-#define GCT_ID_BITMASK		0x08
-
-/* Sequencer: */
-#define SEQ_ADDRESS		0x03C4
-#define SEQ_ADDRESS_R		0x03C5
-#define SEQ_ADDRESS_W		0x03C5
-#define SEQ_ID_RESET		0x00
-#define SEQ_ID_CLOCKING_MODE	0x01
-#define SEQ_ID_MAP_MASK		0x02
-#define SEQ_ID_CHAR_MAP_SELECT	0x03
-#define SEQ_ID_MEMORY_MODE	0x04
-#define SEQ_ID_UNKNOWN1		0x05
-#define SEQ_ID_UNKNOWN2		0x06
-#define SEQ_ID_UNKNOWN3		0x07
-/* S3 extensions */
-#define SEQ_ID_UNLOCK_EXT	0x08
-#define SEQ_ID_EXT_SEQ_REG9	0x09
-#define SEQ_ID_BUS_REQ_CNTL	0x0A
-#define SEQ_ID_EXT_MISC_SEQ	0x0B
-#define SEQ_ID_UNKNOWN4		0x0C
-#define SEQ_ID_EXT_SEQ		0x0D
-#define SEQ_ID_UNKNOWN5		0x0E
-#define SEQ_ID_UNKNOWN6		0x0F
-#define SEQ_ID_MCLK_LO		0x10
-#define SEQ_ID_MCLK_HI		0x11
-#define SEQ_ID_DCLK_LO		0x12
-#define SEQ_ID_DCLK_HI		0x13
-#define SEQ_ID_CLKSYN_CNTL_1	0x14
-#define SEQ_ID_CLKSYN_CNTL_2	0x15
-#define SEQ_ID_CLKSYN_TEST_HI	0x16	/* reserved for S3 testing of the */
-#define SEQ_ID_CLKSYN_TEST_LO	0x17	/*   internal clock synthesizer   */
-#define SEQ_ID_RAMDAC_CNTL	0x18
-#define SEQ_ID_MORE_MAGIC	0x1A
-
-/* CRT Controller: */
-#define CRT_ADDRESS		0x03D4
-#define CRT_ADDRESS_R		0x03D5
-#define CRT_ADDRESS_W		0x03D5
-#define CRT_ID_HOR_TOTAL	0x00
-#define CRT_ID_HOR_DISP_ENA_END	0x01
-#define CRT_ID_START_HOR_BLANK	0x02
-#define CRT_ID_END_HOR_BLANK	0x03
-#define CRT_ID_START_HOR_RETR	0x04
-#define CRT_ID_END_HOR_RETR	0x05
-#define CRT_ID_VER_TOTAL	0x06
-#define CRT_ID_OVERFLOW		0x07
-#define CRT_ID_PRESET_ROW_SCAN	0x08
-#define CRT_ID_MAX_SCAN_LINE	0x09
-#define CRT_ID_CURSOR_START	0x0A
-#define CRT_ID_CURSOR_END	0x0B
-#define CRT_ID_START_ADDR_HIGH	0x0C
-#define CRT_ID_START_ADDR_LOW	0x0D
-#define CRT_ID_CURSOR_LOC_HIGH	0x0E
-#define CRT_ID_CURSOR_LOC_LOW	0x0F
-#define CRT_ID_START_VER_RETR	0x10
-#define CRT_ID_END_VER_RETR	0x11
-#define CRT_ID_VER_DISP_ENA_END	0x12
-#define CRT_ID_SCREEN_OFFSET	0x13
-#define CRT_ID_UNDERLINE_LOC	0x14
-#define CRT_ID_START_VER_BLANK	0x15
-#define CRT_ID_END_VER_BLANK	0x16
-#define CRT_ID_MODE_CONTROL	0x17
-#define CRT_ID_LINE_COMPARE	0x18
-#define CRT_ID_GD_LATCH_RBACK	0x22
-#define CRT_ID_ACT_TOGGLE_RBACK	0x24
-#define CRT_ID_ACT_INDEX_RBACK	0x26
-/* S3 extensions: S3 VGA Registers */
-#define CRT_ID_DEVICE_HIGH	0x2D
-#define CRT_ID_DEVICE_LOW	0x2E
-#define CRT_ID_REVISION 	0x2F
-#define CRT_ID_CHIP_ID_REV	0x30
-#define CRT_ID_MEMORY_CONF	0x31
-#define CRT_ID_BACKWAD_COMP_1	0x32
-#define CRT_ID_BACKWAD_COMP_2	0x33
-#define CRT_ID_BACKWAD_COMP_3	0x34
-#define CRT_ID_REGISTER_LOCK	0x35
-#define CRT_ID_CONFIG_1 	0x36
-#define CRT_ID_CONFIG_2 	0x37
-#define CRT_ID_REGISTER_LOCK_1	0x38
-#define CRT_ID_REGISTER_LOCK_2	0x39
-#define CRT_ID_MISC_1		0x3A
-#define CRT_ID_DISPLAY_FIFO	0x3B
-#define CRT_ID_LACE_RETR_START	0x3C
-/* S3 extensions: System Control Registers  */
-#define CRT_ID_SYSTEM_CONFIG	0x40
-#define CRT_ID_BIOS_FLAG	0x41
-#define CRT_ID_LACE_CONTROL	0x42
-#define CRT_ID_EXT_MODE 	0x43
-#define CRT_ID_HWGC_MODE	0x45	/* HWGC = Hardware Graphics Cursor */
-#define CRT_ID_HWGC_ORIGIN_X_HI	0x46
-#define CRT_ID_HWGC_ORIGIN_X_LO	0x47
-#define CRT_ID_HWGC_ORIGIN_Y_HI	0x48
-#define CRT_ID_HWGC_ORIGIN_Y_LO	0x49
-#define CRT_ID_HWGC_FG_STACK	0x4A
-#define CRT_ID_HWGC_BG_STACK	0x4B
-#define CRT_ID_HWGC_START_AD_HI	0x4C
-#define CRT_ID_HWGC_START_AD_LO	0x4D
-#define CRT_ID_HWGC_DSTART_X	0x4E
-#define CRT_ID_HWGC_DSTART_Y	0x4F
-/* S3 extensions: System Extension Registers  */
-#define CRT_ID_EXT_SYS_CNTL_1	0x50
-#define CRT_ID_EXT_SYS_CNTL_2	0x51
-#define CRT_ID_EXT_BIOS_FLAG_1	0x52
-#define CRT_ID_EXT_MEM_CNTL_1	0x53
-#define CRT_ID_EXT_MEM_CNTL_2	0x54
-#define CRT_ID_EXT_DAC_CNTL	0x55
-#define CRT_ID_EX_SYNC_1	0x56
-#define CRT_ID_EX_SYNC_2	0x57
-#define CRT_ID_LAW_CNTL		0x58	/* LAW = Linear Address Window */
-#define CRT_ID_LAW_POS_HI	0x59
-#define CRT_ID_LAW_POS_LO	0x5A
-#define CRT_ID_GOUT_PORT	0x5C
-#define CRT_ID_EXT_HOR_OVF	0x5D
-#define CRT_ID_EXT_VER_OVF	0x5E
-#define CRT_ID_EXT_MEM_CNTL_3	0x60
-#define CRT_ID_EX_SYNC_3	0x63
-#define CRT_ID_EXT_MISC_CNTL	0x65
-#define CRT_ID_EXT_MISC_CNTL_1	0x66
-#define CRT_ID_EXT_MISC_CNTL_2	0x67
-#define CRT_ID_CONFIG_3 	0x68
-#define CRT_ID_EXT_SYS_CNTL_3	0x69
-#define CRT_ID_EXT_SYS_CNTL_4	0x6A
-#define CRT_ID_EXT_BIOS_FLAG_3	0x6B
-#define CRT_ID_EXT_BIOS_FLAG_4	0x6C
-
-/* Enhanced Commands Registers: */
-#define ECR_SUBSYSTEM_STAT	0x42E8
-#define ECR_SUBSYSTEM_CNTL	0x42E8
-#define ECR_ADV_FUNC_CNTL	0x4AE8
-#define ECR_CURRENT_Y_POS	0x82E8
-#define ECR_CURRENT_Y_POS2	0x82EA	/* Trio64 only */
-#define ECR_CURRENT_X_POS	0x86E8
-#define ECR_CURRENT_X_POS2	0x86EA	/* Trio64 only */
-#define ECR_DEST_Y__AX_STEP	0x8AE8
-#define ECR_DEST_Y2__AX_STEP2	0x8AEA	/* Trio64 only */
-#define ECR_DEST_X__DIA_STEP	0x8EE8
-#define ECR_DEST_X2__DIA_STEP2	0x8EEA	/* Trio64 only */
-#define ECR_ERR_TERM		0x92E8
-#define ECR_ERR_TERM2		0x92EA	/* Trio64 only */
-#define ECR_MAJ_AXIS_PIX_CNT	0x96E8
-#define ECR_MAJ_AXIS_PIX_CNT2	0x96EA	/* Trio64 only */
-#define ECR_GP_STAT		0x9AE8	/* GP = Graphics Processor */
-#define ECR_DRAW_CMD		0x9AE8
-#define ECR_DRAW_CMD2		0x9AEA	/* Trio64 only */
-#define ECR_SHORT_STROKE	0x9EE8
-#define ECR_BKGD_COLOR		0xA2E8	/* BKGD = Background */
-#define ECR_FRGD_COLOR		0xA6E8	/* FRGD = Foreground */
-#define ECR_BITPLANE_WRITE_MASK	0xAAE8
-#define ECR_BITPLANE_READ_MASK	0xAEE8
-#define ECR_COLOR_COMPARE	0xB2E8
-#define ECR_BKGD_MIX		0xB6E8
-#define ECR_FRGD_MIX		0xBAE8
-#define ECR_READ_REG_DATA	0xBEE8
-#define ECR_ID_MIN_AXIS_PIX_CNT	0x00
-#define ECR_ID_SCISSORS_TOP	0x01
-#define ECR_ID_SCISSORS_LEFT	0x02
-#define ECR_ID_SCISSORS_BUTTOM	0x03
-#define ECR_ID_SCISSORS_RIGHT	0x04
-#define ECR_ID_PIX_CNTL		0x0A
-#define ECR_ID_MULT_CNTL_MISC_2	0x0D
-#define ECR_ID_MULT_CNTL_MISC	0x0E
-#define ECR_ID_READ_SEL		0x0F
-#define ECR_PIX_TRANS		0xE2E8
-#define ECR_PIX_TRANS_EXT	0xE2EA
-#define ECR_PATTERN_Y		0xEAE8	/* Trio64 only */
-#define ECR_PATTERN_X		0xEAEA	/* Trio64 only */
-
-
-/* Pass-through */
-#define PASS_ADDRESS		0x40001
-#define PASS_ADDRESS_W		0x40001
-
-/* Video DAC */
-#define VDAC_ADDRESS		0x03c8
-#define VDAC_ADDRESS_W		0x03c8
-#define VDAC_ADDRESS_R		0x03c7
-#define VDAC_STATE		0x03c7
-#define VDAC_DATA		0x03c9
-#define VDAC_MASK		0x03c6
-
-
-#define WGfx(ba, idx, val) \
-do { wb_64(ba, GCT_ADDRESS, idx); wb_64(ba, GCT_ADDRESS_W , val); } while (0)
-
-#define WSeq(ba, idx, val) \
-do { wb_64(ba, SEQ_ADDRESS, idx); wb_64(ba, SEQ_ADDRESS_W , val); } while (0)
-
-#define WCrt(ba, idx, val) \
-do { wb_64(ba, CRT_ADDRESS, idx); wb_64(ba, CRT_ADDRESS_W , val); } while (0)
-
-#define WAttr(ba, idx, val) \
-do { \
-  unsigned char tmp;\
-  tmp = rb_64(ba, ACT_ADDRESS_RESET);\
-  wb_64(ba, ACT_ADDRESS_W, idx);\
-  wb_64(ba, ACT_ADDRESS_W, val);\
-} while (0)
-
-#define SetTextPlane(ba, m) \
-do { \
-  WGfx(ba, GCT_ID_READ_MAP_SELECT, m & 3 );\
-  WSeq(ba, SEQ_ID_MAP_MASK, (1 << (m & 3)));\
-} while (0)
-
-     /* --------------------------------- */
-     /* prototypes                        */
-     /* --------------------------------- */
-
-inline unsigned char RAttr(volatile unsigned char * board, short idx);
-inline unsigned char RSeq(volatile unsigned char * board, short idx);
-inline unsigned char RCrt(volatile unsigned char * board, short idx);
-inline unsigned char RGfx(volatile unsigned char * board, short idx);
-inline void cv64_write_port(unsigned short bits,
-			    volatile unsigned char *board);
-inline void cvscreen(int toggle, volatile unsigned char *board);
-inline void gfx_on_off(int toggle, volatile unsigned char *board);
-#if 0
-unsigned short cv64_compute_clock(unsigned long freq);
-int cv_has_4mb(volatile unsigned char * fb);
-void cv64_board_init(void);
-void cv64_load_video_mode(struct fb_var_screeninfo *video_mode);
-#endif
-
-void cvision_bitblt(u_short sx, u_short sy, u_short dx, u_short dy, u_short w,
-		    u_short h);
-void cvision_clear(u_short dx, u_short dy, u_short w, u_short h, u_short bg);
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 323bdf6..818fb09 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -175,7 +175,7 @@
 
 	acquire_console_sem();
 	list_splice(&fb_info->modelist, &old_list);
-	fb_videomode_to_modelist((struct fb_videomode *)buf, i,
+	fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
 				 &fb_info->modelist);
 	if (fb_new_modelist(fb_info)) {
 		fb_destroy_modelist(&fb_info->modelist);
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index bcf9cea..bb20a22 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -401,6 +401,30 @@
 	framebuffer_release(info);
 }
 
+#ifndef MODULE
+static void __init gx1fb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return;
+
+	while ((this_opt = strsep(&options, ","))) {
+		if (!*this_opt)
+			continue;
+
+		if (!strncmp(this_opt, "mode:", 5))
+			strlcpy(mode_option, this_opt + 5, sizeof(mode_option));
+		else if (!strncmp(this_opt, "crt:", 4))
+			crt_option = !!simple_strtoul(this_opt + 4, NULL, 0);
+		else if (!strncmp(this_opt, "panel:", 6))
+			strlcpy(panel_option, this_opt + 6, sizeof(panel_option));
+		else
+			strlcpy(mode_option, this_opt, sizeof(mode_option));
+	}
+}
+#endif
+
 static struct pci_device_id gx1fb_id_table[] = {
 	{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_VIDEO,
 	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
@@ -420,8 +444,11 @@
 static int __init gx1fb_init(void)
 {
 #ifndef MODULE
-	if (fb_get_options("gx1fb", NULL))
+	char *option = NULL;
+
+	if (fb_get_options("gx1fb", &option))
 		return -ENODEV;
+	gx1fb_setup(option);
 #endif
 	return pci_register_driver(&gx1fb_driver);
 }
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index 579195c..aa65ffc 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -264,7 +264,8 @@
 	struct heap_data         cursor_heap;
 	struct vgastate          state;
 	struct i810fb_i2c_chan   chan[3];
-	atomic_t                 use_count;
+	struct mutex		 open_lock;
+	unsigned int		 use_count;
 	u32 pseudo_palette[17];
 	unsigned long mmio_start_phys;
 	u8 __iomem *mmio_start_virtual;
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index b55a12d..ab1b8fe 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -1049,7 +1049,7 @@
 		mode_valid = 1;
 
 	if (!mode_valid && info->monspecs.modedb_len) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -1235,9 +1235,9 @@
 static int i810fb_open(struct fb_info *info, int user)
 {
 	struct i810fb_par *par = info->par;
-	u32 count = atomic_read(&par->use_count);
-	
-	if (count == 0) {
+
+	mutex_lock(&par->open_lock);
+	if (par->use_count == 0) {
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_CMAP;
 		par->state.vgabase = par->mmio_start_virtual;
@@ -1246,7 +1246,8 @@
 		i810_save_vga_state(par);
 	}
 
-	atomic_inc(&par->use_count);
+	par->use_count++;
+	mutex_unlock(&par->open_lock);
 	
 	return 0;
 }
@@ -1254,18 +1255,20 @@
 static int i810fb_release(struct fb_info *info, int user)
 {
 	struct i810fb_par *par = info->par;
-	u32 count;
-	
-	count = atomic_read(&par->use_count);
-	if (count == 0)
-		return -EINVAL;
 
-	if (count == 1) {
+	mutex_lock(&par->open_lock);
+	if (par->use_count == 0) {
+		mutex_unlock(&par->open_lock);
+		return -EINVAL;
+	}
+
+	if (par->use_count == 1) {
 		i810_restore_vga_state(par);
 		restore_vga(&par->state);
 	}
 
-	atomic_dec(&par->use_count);
+	par->use_count--;
+	mutex_unlock(&par->open_lock);
 	
 	return 0;
 }
@@ -1752,6 +1755,8 @@
 static void __devinit i810_init_defaults(struct i810fb_par *par, 
 				      struct fb_info *info)
 {
+	mutex_init(&par->open_lock);
+
 	if (voffset) 
 		v_offset_default = voffset;
 	else if (par->aperture.size > 32 * 1024 * 1024)
@@ -1919,7 +1924,7 @@
 	fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
 				 &info->modelist);
 	if (specs->modedb != NULL) {
-		struct fb_videomode *m;
+		const struct fb_videomode *m;
 
 		if (xres && yres) {
 			if ((m = fb_find_best_mode(&var, &info->modelist))) {
@@ -2016,11 +2021,10 @@
 	par = info->par;
 	par->dev = dev;
 
-	if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) {
+	if (!(info->pixmap.addr = kzalloc(8*1024, GFP_KERNEL))) {
 		i810fb_release_resource(info, par);
 		return -ENOMEM;
 	}
-	memset(info->pixmap.addr, 0, 8*1024);
 	info->pixmap.size = 8*1024;
 	info->pixmap.buf_align = 8;
 	info->pixmap.access_align = 32;
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 655ae0f..90592fb 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -370,7 +370,6 @@
 
 int __init igafb_init(void)
 {
-        extern int con_is_present(void);
         struct fb_info *info;
         struct pci_dev *pdev;
         struct iga_par *par;
@@ -402,12 +401,11 @@
 	
 	size = sizeof(struct fb_info) + sizeof(struct iga_par) + sizeof(u32)*16;
 
-        info = kmalloc(size, GFP_ATOMIC);
+        info = kzalloc(size, GFP_ATOMIC);
         if (!info) {
                 printk("igafb_init: can't alloc fb_info\n");
                 return -ENOMEM;
         }
-        memset(info, 0, size);
 
 	par = (struct iga_par *) (info + 1);
 	
@@ -466,7 +464,7 @@
 	 * one additional region with size == 0. 
 	 */
 
-	par->mmap_map = kmalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC);
+	par->mmap_map = kzalloc(4 * sizeof(*par->mmap_map), GFP_ATOMIC);
 	if (!par->mmap_map) {
 		printk("igafb_init: can't alloc mmap_map\n");
 		iounmap((void *)par->io_base);
@@ -475,8 +473,6 @@
 		return -ENOMEM;
 	}
 
-	memset(par->mmap_map, 0, 4 * sizeof(*par->mmap_map));
-
 	/*
 	 * Set default vmode and cmode from PROM properties.
 	 */
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 664fc5c..b75eda8 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -540,12 +540,11 @@
 	dinfo->pdev  = pdev;
 
 	/* Reserve pixmap space. */
-	info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL);
+	info->pixmap.addr = kzalloc(64 * 1024, GFP_KERNEL);
 	if (info->pixmap.addr == NULL) {
 		ERR_MSG("Cannot reserve pixmap memory.\n");
 		goto err_out_pixmap;
 	}
-	memset(info->pixmap.addr, 0, 64 * 1024);
 
 	/* set early this option because it could be changed by tv encoder
 	   driver */
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c
index fe28848..f64c4a0 100644
--- a/drivers/video/matrox/i2c-matroxfb.c
+++ b/drivers/video/matrox/i2c-matroxfb.c
@@ -146,7 +146,7 @@
 	unsigned long flags;
 	struct matroxfb_dh_maven_info* m2info;
 
-	m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
+	m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
 	if (!m2info)
 		return NULL;
 
@@ -155,8 +155,6 @@
 	matroxfb_DAC_out(PMINFO DAC_XGENIOCTRL, 0x00);
 	matroxfb_DAC_unlock_irqrestore(flags);
 
-	memset(m2info, 0, sizeof(*m2info));
-
 	switch (ACCESS_FBINFO(chip)) {
 		case MGA_2064:
 		case MGA_2164:
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 2c98010..03ae55b 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -694,12 +694,11 @@
 	/* hardware is CRTC2 incapable... */
 	if (!ACCESS_FBINFO(devflags.crtc2))
 		return NULL;
-	m2info = kmalloc(sizeof(*m2info), GFP_KERNEL);
+	m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
 	if (!m2info) {
 		printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
 		return NULL;
 	}
-	memset(m2info, 0, sizeof(*m2info));
 	m2info->primary_dev = MINFO;
 	if (matroxfb_dh_registerfb(m2info)) {
 		kfree(m2info);
diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c
index 472a3ca..15b8b3c 100644
--- a/drivers/video/mbx/mbxdebugfs.c
+++ b/drivers/video/mbx/mbxdebugfs.c
@@ -170,37 +170,37 @@
 }
 
 
-static struct file_operations sysconf_fops = {
+static const struct file_operations sysconf_fops = {
 	.read = sysconf_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations clock_fops = {
+static const struct file_operations clock_fops = {
 	.read = clock_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations display_fops = {
+static const struct file_operations display_fops = {
 	.read = display_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations gsctl_fops = {
+static const struct file_operations gsctl_fops = {
 	.read = gsctl_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations sdram_fops = {
+static const struct file_operations sdram_fops = {
 	.read = sdram_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
 };
 
-static struct file_operations misc_fops = {
+static const struct file_operations misc_fops = {
 	.read = misc_read_file,
 	.write = write_file_dummy,
 	.open = open_file_generic,
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 5df41f6..5162eab 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -610,10 +610,8 @@
 	diff = refresh;
 	best = -1;
 	for (i = 0; i < dbsize; i++) {
-		if ((name_matches(db[i], name, namelen) &&
-			!fb_try_mode(var, info, &db[i], bpp)))
-			return 1;
-		if (res_specified && res_matches(db[i], xres, yres)) {
+		if (name_matches(db[i], name, namelen) ||
+		    (res_specified && res_matches(db[i], xres, yres))) {
 			if(!fb_try_mode(var, info, &db[i], bpp)) {
 				if(!refresh_specified || db[i].refresh == refresh)
 					return 1;
@@ -670,7 +668,7 @@
  * @var: pointer to struct fb_var_screeninfo
  */
 void fb_var_to_videomode(struct fb_videomode *mode,
-			 struct fb_var_screeninfo *var)
+			 const struct fb_var_screeninfo *var)
 {
 	u32 pixclock, hfreq, htotal, vtotal;
 
@@ -714,17 +712,21 @@
  * @mode: pointer to struct fb_videomode
  */
 void fb_videomode_to_var(struct fb_var_screeninfo *var,
-			       struct fb_videomode *mode)
+			 const struct fb_videomode *mode)
 {
 	var->xres = mode->xres;
 	var->yres = mode->yres;
+	var->xres_virtual = mode->xres;
+	var->yres_virtual = mode->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
 	var->pixclock = mode->pixclock;
 	var->left_margin = mode->left_margin;
-	var->hsync_len = mode->hsync_len;
-	var->vsync_len = mode->vsync_len;
 	var->right_margin = mode->right_margin;
 	var->upper_margin = mode->upper_margin;
 	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
 	var->sync = mode->sync;
 	var->vmode = mode->vmode & FB_VMODE_MASK;
 }
@@ -737,8 +739,8 @@
  * RETURNS:
  * 1 if equal, 0 if not
  */
-int fb_mode_is_equal(struct fb_videomode *mode1,
-		     struct fb_videomode *mode2)
+int fb_mode_is_equal(const struct fb_videomode *mode1,
+		     const struct fb_videomode *mode2)
 {
 	return (mode1->xres         == mode2->xres &&
 		mode1->yres         == mode2->yres &&
@@ -770,8 +772,8 @@
  * var->xres and var->yres.  If more than 1 videomode is found, will return
  * the videomode with the highest refresh rate
  */
-struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
-				       struct list_head *head)
+const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+					     struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -808,8 +810,8 @@
  * If more than 1 videomode is found, will return the videomode with
  * the closest refresh rate.
  */
-struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
-					  struct list_head *head)
+const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+					        struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -847,8 +849,8 @@
  * RETURNS:
  * struct fb_videomode, NULL if none found
  */
-struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
-				   struct list_head *head)
+const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+					 struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -872,7 +874,7 @@
  * NOTES:
  * Will only add unmatched mode entries
  */
-int fb_add_videomode(struct fb_videomode *mode, struct list_head *head)
+int fb_add_videomode(const struct fb_videomode *mode, struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
@@ -907,7 +909,8 @@
  * NOTES:
  * Will remove all matching mode entries
  */
-void fb_delete_videomode(struct fb_videomode *mode, struct list_head *head)
+void fb_delete_videomode(const struct fb_videomode *mode,
+			 struct list_head *head)
 {
 	struct list_head *pos, *n;
 	struct fb_modelist *modelist;
@@ -943,7 +946,7 @@
  * @num: number of entries in array
  * @head: struct list_head of modelist
  */
-void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
 			      struct list_head *head)
 {
 	int i;
@@ -956,12 +959,12 @@
 	}
 }
 
-struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
-					  struct list_head *head)
+const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+					        struct list_head *head)
 {
 	struct list_head *pos;
 	struct fb_modelist *modelist;
-	struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
+	const struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
 	int first = 0;
 
 	if (!head->prev || !head->next || list_empty(head))
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index deaf820..395cced 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -66,7 +66,6 @@
 #include <linux/init.h>
 #ifdef CONFIG_TOSHIBA
 #include <linux/toshiba.h>
-extern int tosh_smm(SMMRegisters *regs);
 #endif
 
 #include <asm/io.h>
@@ -557,14 +556,16 @@
 neofb_open(struct fb_info *info, int user)
 {
 	struct neofb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
-	if (!cnt) {
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
 		save_vga(&par->state);
 	}
-	atomic_inc(&par->ref_count);
+	par->ref_count++;
+	mutex_unlock(&par->open_lock);
+
 	return 0;
 }
 
@@ -572,14 +573,18 @@
 neofb_release(struct fb_info *info, int user)
 {
 	struct neofb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
-	if (!cnt)
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
+		mutex_unlock(&par->open_lock);
 		return -EINVAL;
-	if (cnt == 1) {
+	}
+	if (par->ref_count == 1) {
 		restore_vga(&par->state);
 	}
-	atomic_dec(&par->ref_count);
+	par->ref_count--;
+	mutex_unlock(&par->open_lock);
+
 	return 0;
 }
 
@@ -2048,6 +2053,7 @@
 
 	info->fix.accel = id->driver_data;
 
+	mutex_init(&par->open_lock);
 	par->pci_burst = !nopciburst;
 	par->lcd_stretch = !nostretch;
 	par->libretto = libretto;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 538e947..8e5b484 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -829,7 +829,7 @@
 	}
 
 	if (!mode_valid) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -1046,10 +1046,10 @@
 	}
 
 	if (specs->modedb != NULL) {
-		struct fb_videomode *modedb;
+		const struct fb_videomode *mode;
 
-		modedb = fb_find_best_display(specs, &info->modelist);
-		fb_videomode_to_var(&nvidiafb_default_var, modedb);
+		mode = fb_find_best_display(specs, &info->modelist);
+		fb_videomode_to_var(&nvidiafb_default_var, mode);
 		nvidiafb_default_var.bits_per_pixel = bpp;
 	} else if (par->fpWidth && par->fpHeight) {
 		char buf[16];
@@ -1205,13 +1205,11 @@
 	par = info->par;
 	par->pci_dev = pd;
 
-	info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
+	info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
 
 	if (info->pixmap.addr == NULL)
 		goto err_out_kfree;
 
-	memset(info->pixmap.addr, 0, 8 * 1024);
-
 	if (pci_enable_device(pd)) {
 		printk(KERN_ERR PFX "cannot enable PCI device\n");
 		goto err_out_enable;
@@ -1347,7 +1345,7 @@
 	return -ENODEV;
 }
 
-static void __exit nvidiafb_remove(struct pci_dev *pd)
+static void __devexit nvidiafb_remove(struct pci_dev *pd)
 {
 	struct fb_info *info = pci_get_drvdata(pd);
 	struct nvidia_par *par = info->par;
@@ -1433,7 +1431,7 @@
 	.probe    = nvidiafb_probe,
 	.suspend  = nvidiafb_suspend,
 	.resume   = nvidiafb_resume,
-	.remove   = __exit_p(nvidiafb_remove),
+	.remove   = __devexit_p(nvidiafb_remove),
 };
 
 /* ------------------------------------------------------------------------- *
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 1d81ef4..bd787e8 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -3299,14 +3299,12 @@
 		fb_info[i].dev = NULL;
 	}
 
-	dev =
-	    pci_find_device(PCI_VENDOR_ID_3DLABS,
+	dev = pci_get_device(PCI_VENDOR_ID_3DLABS,
 			    PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev);
 
 	for (i = 0; ((i < PM3_MAX_BOARD) && dev); i++) {
 		dev_array[i] = dev;
-		dev =
-		    pci_find_device(PCI_VENDOR_ID_3DLABS,
+		dev = pci_get_device(PCI_VENDOR_ID_3DLABS,
 				    PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev);
 	}
 
@@ -3353,7 +3351,7 @@
 	/* now, initialize... or not */
 	for (i = 0; i < PM3_MAX_BOARD; i++) {
 		l_fb_info = &(fb_info[i]);
-		if ((l_fb_info->dev) && (!disable[i])) {	/* PCI device was found and not disabled by user */
+		if (l_fb_info->dev && !disable[i]) {	/* PCI device was found and not disabled by user */
 			DPRINTK(2,
 				"found @%lx Vendor %lx Device %lx ; base @ : %lx - %lx - %lx - %lx - %lx - %lx, irq %ld\n",
 				(unsigned long) l_fb_info->dev,
@@ -3608,7 +3606,7 @@
 
 	pm3fb_init();
 
-	return (0);
+	return 0;
 }
 
 void cleanup_module(void)
@@ -3619,23 +3617,18 @@
 		struct pm3fb_info *l_fb_info;
 		for (i = 0; i < PM3_MAX_BOARD; i++) {
 			l_fb_info = &(fb_info[i]);
-			if ((l_fb_info->dev != NULL)
-			    && (!(disable[l_fb_info->board_num]))) {
-				if (l_fb_info->vIOBase !=
-				    (unsigned char *) -1) {
+			pci_dev_put(l_fb_info->dev);
+			if (l_fb_info->dev != NULL  && !(disable[l_fb_info->board_num])) {
+				if (l_fb_info->vIOBase != (unsigned char *) -1) {
 					pm3fb_unmapIO(l_fb_info);
 					release_mem_region(l_fb_info->p_fb,
-							   l_fb_info->
-							   fb_size);
-					release_mem_region(l_fb_info->
-							   pIOBase,
-							   PM3_REGS_SIZE);
+						   l_fb_info->fb_size);
+					release_mem_region(l_fb_info->pIOBase,
+						   PM3_REGS_SIZE);
 				}
-				unregister_framebuffer(&l_fb_info->gen.
-						       info);
+				unregister_framebuffer(&l_fb_info->gen.info);
 			}
 		}
 	}
-	return;
 }
 #endif /* MODULE */
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
new file mode 100644
index 0000000..81e43cd
--- /dev/null
+++ b/drivers/video/ps3fb.c
@@ -0,0 +1,1229 @@
+/*
+ *  linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device
+ *
+ *	Copyright (C) 2006 Sony Computer Entertainment Inc.
+ *	Copyright 2006, 2007 Sony Corporation
+ *
+ *  This file is based on :
+ *
+ *  linux/drivers/video/vfb.c -- Virtual frame buffer device
+ *
+ *	Copyright (C) 2002 James Simmons
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/console.h>
+#include <linux/ioctl.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <asm/time.h>
+
+#include <asm/abs_addr.h>
+#include <asm/lv1call.h>
+#include <asm/ps3av.h>
+#include <asm/ps3fb.h>
+#include <asm/ps3.h>
+
+#ifdef PS3FB_DEBUG
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC	0x101
+#define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP	0x102
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP	0x600
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT		0x601
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT_SYNC	0x602
+
+#define L1GPU_FB_BLIT_WAIT_FOR_COMPLETION	(1ULL << 32)
+
+#define L1GPU_DISPLAY_SYNC_HSYNC		1
+#define L1GPU_DISPLAY_SYNC_VSYNC		2
+
+#define DDR_SIZE				(0)	/* used no ddr */
+#define GPU_OFFSET				(64 * 1024)
+#define GPU_IOIF				(0x0d000000UL)
+
+#define PS3FB_FULL_MODE_BIT			0x80
+
+#define GPU_INTR_STATUS_VSYNC_0			0	/* vsync on head A */
+#define GPU_INTR_STATUS_VSYNC_1			1	/* vsync on head B */
+#define GPU_INTR_STATUS_FLIP_0			3	/* flip head A */
+#define GPU_INTR_STATUS_FLIP_1			4	/* flip head B */
+#define GPU_INTR_STATUS_QUEUE_0			5	/* queue head A */
+#define GPU_INTR_STATUS_QUEUE_1			6	/* queue head B */
+
+#define GPU_DRIVER_INFO_VERSION			0x211
+
+/* gpu internals */
+struct display_head {
+	u64 be_time_stamp;
+	u32 status;
+	u32 offset;
+	u32 res1;
+	u32 res2;
+	u32 field;
+	u32 reserved1;
+
+	u64 res3;
+	u32 raster;
+
+	u64 vblank_count;
+	u32 field_vsync;
+	u32 reserved2;
+};
+
+struct gpu_irq {
+	u32 irq_outlet;
+	u32 status;
+	u32 mask;
+	u32 video_cause;
+	u32 graph_cause;
+	u32 user_cause;
+
+	u32 res1;
+	u64 res2;
+
+	u32 reserved[4];
+};
+
+struct gpu_driver_info {
+	u32 version_driver;
+	u32 version_gpu;
+	u32 memory_size;
+	u32 hardware_channel;
+
+	u32 nvcore_frequency;
+	u32 memory_frequency;
+
+	u32 reserved[1063];
+	struct display_head display_head[8];
+	struct gpu_irq irq;
+};
+
+struct ps3fb_priv {
+	unsigned int irq_no;
+	void *dev;
+
+	u64 context_handle, memory_handle;
+	void *xdr_ea;
+	struct gpu_driver_info *dinfo;
+	struct semaphore sem;
+	u32 res_index;
+
+	u64 vblank_count;	/* frame count */
+	wait_queue_head_t wait_vsync;
+
+	u32 num_frames;		/* num of frame buffers */
+	atomic_t ext_flip;	/* on/off flip with vsync */
+	atomic_t f_count;	/* fb_open count */
+	int is_blanked;
+};
+static struct ps3fb_priv ps3fb;
+
+struct ps3fb_res_table {
+	u32 xres;
+	u32 yres;
+	u32 xoff;
+	u32 yoff;
+	u32 type;
+};
+#define PS3FB_RES_FULL 1
+static const struct ps3fb_res_table ps3fb_res[] = {
+	/* res_x,y   margin_x,y  full */
+	{  720,  480,  72,  48 , 0},
+	{  720,  576,  72,  58 , 0},
+	{ 1280,  720,  78,  38 , 0},
+	{ 1920, 1080, 116,  58 , 0},
+	/* full mode */
+	{  720,  480,   0,   0 , PS3FB_RES_FULL},
+	{  720,  576,   0,   0 , PS3FB_RES_FULL},
+	{ 1280,  720,   0,   0 , PS3FB_RES_FULL},
+	{ 1920, 1080,   0,   0 , PS3FB_RES_FULL},
+	/* vesa: normally full mode */
+	{ 1280,  768,   0,   0 , 0},
+	{ 1280, 1024,   0,   0 , 0},
+	{ 1920, 1200,   0,   0 , 0},
+	{    0,    0,   0,   0 , 0} };
+
+/* default resolution */
+#define GPU_RES_INDEX 0		/* 720 x 480 */
+
+static const struct fb_videomode ps3fb_modedb[] = {
+    /* 60 Hz broadcast modes (modes "1" to "5") */
+    {
+        /* 480i */
+        "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 480p */
+        "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080i */
+        "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (modes "6" to "10") */
+    {
+        /* 576i */
+        "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 576p */
+        "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 720p */
+        "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },    {
+        /* 1080 */
+        "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    },    {
+        /* 1080p */
+        "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5,
+        FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* VESA modes (modes "11" to "13") */
+    {
+	/* WXGA */
+	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* SXGA */
+	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* WUXGA */
+	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
+	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    },
+
+    /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */
+    {
+	/* 480if */
+	"480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 480pf */
+	"480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */
+    {
+	/* 576if */
+	"576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 576pf */
+	"576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 720pf */
+	"720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1080if */
+	"1080f", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
+    }, {
+	/* 1080pf */
+	"1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
+	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    }
+};
+
+
+#define HEAD_A
+#define HEAD_B
+
+#define X_OFF(i)	(ps3fb_res[i].xoff)	/* left/right margin (pixel) */
+#define Y_OFF(i)	(ps3fb_res[i].yoff)	/* top/bottom margin (pixel) */
+#define WIDTH(i)	(ps3fb_res[i].xres)	/* width of FB */
+#define HEIGHT(i)	(ps3fb_res[i].yres)	/* height of FB */
+#define BPP	4		/* number of bytes per pixel */
+#define VP_OFF(i)	(WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP)
+#define FB_OFF(i)	(GPU_OFFSET - VP_OFF(i) % GPU_OFFSET)
+
+static int ps3fb_mode = 0;
+module_param(ps3fb_mode, bool, 0);
+
+static char *mode_option __initdata = NULL;
+
+
+static int ps3fb_get_res_table(u32 xres, u32 yres)
+{
+	int full_mode;
+	unsigned int i;
+	u32 x, y, f;
+
+	full_mode = (ps3fb_mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0;
+	for (i = 0;; i++) {
+		x = ps3fb_res[i].xres;
+		y = ps3fb_res[i].yres;
+		f = ps3fb_res[i].type;
+
+		if (!x) {
+			DPRINTK("ERROR: ps3fb_get_res_table()\n");
+			return -1;
+		}
+
+		if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL)
+			continue;
+
+		if (x == xres && (yres == 0 || y == yres))
+			break;
+
+		x = x - 2 * ps3fb_res[i].xoff;
+		y = y - 2 * ps3fb_res[i].yoff;
+		if (x == xres && (yres == 0 || y == yres))
+			break;
+	}
+	return i;
+}
+
+static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,
+				    u32 *line_length)
+{
+	unsigned int i, mode;
+
+	for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++)
+		if (var->xres == ps3fb_modedb[i].xres &&
+		    var->yres == ps3fb_modedb[i].yres &&
+		    var->pixclock == ps3fb_modedb[i].pixclock &&
+		    var->hsync_len == ps3fb_modedb[i].hsync_len &&
+		    var->vsync_len == ps3fb_modedb[i].vsync_len &&
+		    var->left_margin == ps3fb_modedb[i].left_margin &&
+		    var->right_margin == ps3fb_modedb[i].right_margin &&
+		    var->upper_margin == ps3fb_modedb[i].upper_margin &&
+		    var->lower_margin == ps3fb_modedb[i].lower_margin &&
+		    var->sync == ps3fb_modedb[i].sync &&
+		    (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) {
+			/* Cropped broadcast modes use the full line_length */
+			*line_length =
+			    ps3fb_modedb[i < 10 ? i + 13 : i].xres * 4;
+			/* Full broadcast modes have the full mode bit set */
+			mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
+
+			DPRINTK("ps3fb_find_mode: mode %u\n", mode);
+			return mode;
+		}
+
+	DPRINTK("ps3fb_find_mode: mode not found\n");
+	return 0;
+
+}
+
+static const struct fb_videomode *ps3fb_default_mode(void)
+{
+	u32 mode = ps3fb_mode & PS3AV_MODE_MASK;
+	u32 flags;
+
+	if (mode < 1 || mode > 13)
+		return NULL;
+
+	flags = ps3fb_mode & ~PS3AV_MODE_MASK;
+
+	if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) {
+		/* Full broadcast mode */
+		return &ps3fb_modedb[mode + 12];
+	}
+
+	return &ps3fb_modedb[mode - 1];
+}
+
+static int ps3fb_sync(u32 frame)
+{
+	int i, status;
+	u32 xres, yres;
+	u64 fb_ioif, offset;
+
+	i = ps3fb.res_index;
+	xres = ps3fb_res[i].xres;
+	yres = ps3fb_res[i].yres;
+
+	if (frame > ps3fb.num_frames - 1) {
+		printk(KERN_WARNING "%s: invalid frame number (%u)\n",
+		       __FUNCTION__, frame);
+		return -EINVAL;
+	}
+	offset = xres * yres * BPP * frame;
+
+	fb_ioif = GPU_IOIF + FB_OFF(i) + offset;
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
+					   offset, fb_ioif,
+					   L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
+					   (xres << 16) | yres,
+					   xres * BPP);	/* line_length */
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
+		       __FUNCTION__, status);
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
+					   0, offset, 0, 0);
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __FUNCTION__, status);
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP,
+					   1, offset, 0, 0);
+	if (status)
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n",
+		       __FUNCTION__, status);
+#endif
+	return 0;
+}
+
+
+static int ps3fb_open(struct fb_info *info, int user)
+{
+	atomic_inc(&ps3fb.f_count);
+	return 0;
+}
+
+static int ps3fb_release(struct fb_info *info, int user)
+{
+	if (atomic_dec_and_test(&ps3fb.f_count)) {
+		if (atomic_read(&ps3fb.ext_flip)) {
+			atomic_set(&ps3fb.ext_flip, 0);
+			ps3fb_sync(0);	/* single buffer */
+		}
+	}
+	return 0;
+}
+
+    /*
+     *  Setting the video mode has been split into two parts.
+     *  First part, xxxfb_check_var, must not write anything
+     *  to hardware, it should only verify and adjust var.
+     *  This means it doesn't alter par but it does use hardware
+     *  data from it to check this var.
+     */
+
+static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u32 line_length;
+	int mode;
+	int i;
+
+	DPRINTK("var->xres:%u info->var.xres:%u\n", var->xres, info->var.xres);
+	DPRINTK("var->yres:%u info->var.yres:%u\n", var->yres, info->var.yres);
+
+	/* FIXME For now we do exact matches only */
+	mode = ps3fb_find_mode(var, &line_length);
+	if (!mode)
+		return -EINVAL;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/* Virtual screen and panning are not supported */
+	if (var->xres_virtual > var->xres || var->yres_virtual > var->yres ||
+	    var->xoffset || var->yoffset) {
+		DPRINTK("Virtual screen and panning are not supported\n");
+		return -EINVAL;
+	}
+
+	var->xres_virtual = var->xres;
+	var->yres_virtual = var->yres;
+
+	/* We support ARGB8888 only */
+	if (var->bits_per_pixel > 32 || var->grayscale ||
+	    var->red.offset > 16 || var->green.offset > 8 ||
+	    var->blue.offset > 0 || var->transp.offset > 24 ||
+	    var->red.length > 8 || var->green.length > 8 ||
+	    var->blue.length > 8 || var->transp.length > 8 ||
+	    var->red.msb_right || var->green.msb_right ||
+	    var->blue.msb_right || var->transp.msb_right || var->nonstd) {
+		DPRINTK("We support ARGB8888 only\n");
+		return -EINVAL;
+	}
+
+	var->bits_per_pixel = 32;
+	var->red.offset = 16;
+	var->green.offset = 8;
+	var->blue.offset = 0;
+	var->transp.offset = 24;
+	var->red.length = 8;
+	var->green.length = 8;
+	var->blue.length = 8;
+	var->transp.length = 8;
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	/* Rotation is not supported */
+	if (var->rotate) {
+		DPRINTK("Rotation is not supported\n");
+		return -EINVAL;
+	}
+
+	/* Memory limit */
+	i = ps3fb_get_res_table(var->xres, var->yres);
+	if (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP > ps3fb_videomemory.size) {
+		DPRINTK("Not enough memory\n");
+		return -ENOMEM;
+	}
+
+	var->height = -1;
+	var->width = -1;
+
+	return 0;
+}
+
+    /*
+     * This routine actually sets the video mode.
+     */
+
+static int ps3fb_set_par(struct fb_info *info)
+{
+	unsigned int mode;
+	int i;
+	unsigned long offset;
+	static int first = 1;
+
+	DPRINTK("xres:%d xv:%d yres:%d yv:%d clock:%d\n",
+		info->var.xres, info->var.xres_virtual,
+		info->var.yres, info->var.yres_virtual, info->var.pixclock);
+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
+	ps3fb.res_index = i;
+
+	mode = ps3fb_find_mode(&info->var, &info->fix.line_length);
+	if (!mode)
+		return -EINVAL;
+
+	offset = FB_OFF(i) + VP_OFF(i);
+	info->fix.smem_len = ps3fb_videomemory.size - offset;
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
+
+	ps3fb.num_frames = ps3fb_videomemory.size/
+			   (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP);
+
+	/* Keep the special bits we cannot set using fb_var_screeninfo */
+	ps3fb_mode = (ps3fb_mode & ~PS3AV_MODE_MASK) | mode;
+
+	if (ps3av_set_video_mode(ps3fb_mode, first))
+		return -EINVAL;
+
+	first = 0;
+	return 0;
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+
+static int ps3fb_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp, struct fb_info *info)
+{
+	if (regno >= 16)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	transp >>= 8;
+
+	((u32 *)info->pseudo_palette)[regno] = transp << 24 | red << 16 |
+					       green << 8 | blue;
+	return 0;
+}
+
+    /*
+     *  As we have a virtual frame buffer, we need our own mmap function
+     */
+
+static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	unsigned long size, offset;
+	int i;
+
+	i = ps3fb_get_res_table(info->var.xres, info->var.yres);
+	if (i == -1)
+		return -EINVAL;
+
+	size = vma->vm_end - vma->vm_start;
+	offset = vma->vm_pgoff << PAGE_SHIFT;
+	if (offset + size > info->fix.smem_len)
+		return -EINVAL;
+
+	offset += info->fix.smem_start + FB_OFF(i) + VP_OFF(i);
+	if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
+			    size, vma->vm_page_prot))
+		return -EAGAIN;
+
+	printk(KERN_DEBUG "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", offset,
+	       vma->vm_start);
+	return 0;
+}
+
+    /*
+     * Blank the display
+     */
+
+static int ps3fb_blank(int blank, struct fb_info *info)
+{
+	int retval;
+
+	DPRINTK("%s: blank:%d\n", __FUNCTION__, blank);
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		retval = ps3av_video_mute(1);	/* mute on */
+		if (!retval)
+			ps3fb.is_blanked = 1;
+		break;
+
+	default:		/* unblank */
+		retval = ps3av_video_mute(0);	/* mute off */
+		if (!retval)
+			ps3fb.is_blanked = 0;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fb_get_vblank(struct fb_vblank *vblank)
+{
+	memset(vblank, 0, sizeof(&vblank));
+	vblank->flags = FB_VBLANK_HAVE_VSYNC;
+	return 0;
+}
+
+int ps3fb_wait_for_vsync(u32 crtc)
+{
+	int ret;
+	u64 count;
+
+	count = ps3fb.vblank_count;
+	ret = wait_event_interruptible_timeout(ps3fb.wait_vsync,
+					       count != ps3fb.vblank_count,
+					       HZ / 10);
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync);
+
+void ps3fb_flip_ctl(int on)
+{
+	if (on) {
+		if (atomic_read(&ps3fb.ext_flip) > 0) {
+			atomic_dec(&ps3fb.ext_flip);
+		}
+	} else {
+		atomic_inc(&ps3fb.ext_flip);
+	}
+}
+
+EXPORT_SYMBOL_GPL(ps3fb_flip_ctl);
+
+    /*
+     * ioctl
+     */
+
+static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
+		       unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	u32 val, old_mode;
+	int retval = -EFAULT;
+
+	switch (cmd) {
+	case FBIOGET_VBLANK:
+		{
+			struct fb_vblank vblank;
+			DPRINTK("FBIOGET_VBLANK:\n");
+			retval = ps3fb_get_vblank(&vblank);
+			if (retval)
+				break;
+
+			if (copy_to_user(argp, &vblank, sizeof(vblank)))
+				retval = -EFAULT;
+			break;
+		}
+
+	case FBIO_WAITFORVSYNC:
+		{
+			u32 crt;
+			DPRINTK("FBIO_WAITFORVSYNC:\n");
+			if (get_user(crt, (u32 __user *) arg))
+				break;
+
+			retval = ps3fb_wait_for_vsync(crt);
+			break;
+		}
+
+	case PS3FB_IOCTL_SETMODE:
+		{
+			const struct fb_videomode *mode;
+			struct fb_var_screeninfo var;
+
+			if (copy_from_user(&val, argp, sizeof(val)))
+				break;
+
+			DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val);
+			retval = -EINVAL;
+			old_mode = ps3fb_mode;
+			ps3fb_mode = val;
+			mode = ps3fb_default_mode();
+			if (mode) {
+				var = info->var;
+				fb_videomode_to_var(&var, mode);
+				acquire_console_sem();
+				info->flags |= FBINFO_MISC_USEREVENT;
+				/* Force, in case only special bits changed */
+				var.activate |= FB_ACTIVATE_FORCE;
+				retval = fb_set_var(info, &var);
+				info->flags &= ~FBINFO_MISC_USEREVENT;
+				release_console_sem();
+			}
+			if (retval)
+				ps3fb_mode = old_mode;
+			break;
+		}
+
+	case PS3FB_IOCTL_GETMODE:
+		val = ps3av_get_mode();
+		DPRINTK("PS3FB_IOCTL_GETMODE:%x\n", val);
+		if (!copy_to_user(argp, &val, sizeof(val)))
+			retval = 0;
+		break;
+
+	case PS3FB_IOCTL_SCREENINFO:
+		{
+			struct ps3fb_ioctl_res res;
+			int i = ps3fb.res_index;
+			DPRINTK("PS3FB_IOCTL_SCREENINFO:\n");
+			res.xres = ps3fb_res[i].xres;
+			res.yres = ps3fb_res[i].yres;
+			res.xoff = ps3fb_res[i].xoff;
+			res.yoff = ps3fb_res[i].yoff;
+			res.num_frames = ps3fb.num_frames;
+			if (!copy_to_user(argp, &res, sizeof(res)))
+				retval = 0;
+			break;
+		}
+
+	case PS3FB_IOCTL_ON:
+		DPRINTK("PS3FB_IOCTL_ON:\n");
+		atomic_inc(&ps3fb.ext_flip);
+		retval = 0;
+		break;
+
+	case PS3FB_IOCTL_OFF:
+		DPRINTK("PS3FB_IOCTL_OFF:\n");
+		if (atomic_read(&ps3fb.ext_flip) > 0)
+			atomic_dec(&ps3fb.ext_flip);
+		retval = 0;
+		break;
+
+	case PS3FB_IOCTL_FSEL:
+		if (copy_from_user(&val, argp, sizeof(val)))
+			break;
+
+		DPRINTK("PS3FB_IOCTL_FSEL:%d\n", val);
+		retval = ps3fb_sync(val);
+		break;
+
+	default:
+		retval = -ENOIOCTLCMD;
+		break;
+	}
+	return retval;
+}
+
+static int ps3fbd(void *arg)
+{
+	daemonize("ps3fbd");
+	for (;;) {
+		down(&ps3fb.sem);
+		if (atomic_read(&ps3fb.ext_flip) == 0)
+			ps3fb_sync(0);	/* single buffer */
+	}
+	return 0;
+}
+
+static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
+{
+	u64 v1;
+	int status;
+	struct display_head *head = &ps3fb.dinfo->display_head[1];
+
+	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n",
+		       __FUNCTION__, status);
+		return IRQ_NONE;
+	}
+
+	if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
+		/* VSYNC */
+		ps3fb.vblank_count = head->vblank_count;
+		if (!ps3fb.is_blanked)
+			up(&ps3fb.sem);
+		wake_up_interruptible(&ps3fb.wait_vsync);
+	}
+
+	return IRQ_HANDLED;
+}
+
+#ifndef MODULE
+static int __init ps3fb_setup(char *options)
+{
+	char *this_opt;
+	int mode = 0;
+
+	if (!options || !*options)
+		return 0;	/* no options */
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (!strncmp(this_opt, "mode:", 5))
+			mode = simple_strtoul(this_opt + 5, NULL, 0);
+		else
+			mode_option = this_opt;
+	}
+	return mode;
+}
+#endif	/* MODULE */
+
+    /*
+     *  Initialisation
+     */
+
+static void ps3fb_platform_release(struct device *device)
+{
+	/* This is called when the reference count goes to zero. */
+}
+
+static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev)
+{
+	int error;
+
+	DPRINTK("version_driver:%x\n", dinfo->version_driver);
+	DPRINTK("irq outlet:%x\n", dinfo->irq.irq_outlet);
+	DPRINTK("version_gpu:%x memory_size:%x ch:%x core_freq:%d mem_freq:%d\n",
+		dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel,
+		dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000);
+
+	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
+		printk(KERN_ERR "%s: version_driver err:%x\n", __FUNCTION__,
+		       dinfo->version_driver);
+		return -EINVAL;
+	}
+
+	ps3fb.dev = dev;
+	error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
+			      &ps3fb.irq_no);
+	if (error) {
+		printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__,
+		       error);
+		return error;
+	}
+
+	error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED,
+			    "ps3fb vsync", ps3fb.dev);
+	if (error) {
+		printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__,
+		       error);
+		ps3_free_irq(ps3fb.irq_no);
+		return error;
+	}
+
+	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
+			  (1 << GPU_INTR_STATUS_FLIP_1);
+	return 0;
+}
+
+static int ps3fb_xdr_settings(u64 xdr_lpar)
+{
+	int status;
+
+	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
+				       xdr_lpar, ps3fb_videomemory.size, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n",
+		       __FUNCTION__, status);
+		return -ENXIO;
+	}
+	DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
+		ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar,
+		virt_to_abs(ps3fb.xdr_ea), ps3fb_videomemory.size);
+
+	status = lv1_gpu_context_attribute(ps3fb.context_handle,
+					   L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
+					   xdr_lpar, ps3fb_videomemory.size,
+					   GPU_IOIF, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n",
+		       __FUNCTION__, status);
+		return -ENXIO;
+	}
+	return 0;
+}
+
+static struct fb_ops ps3fb_ops = {
+	.fb_open	= ps3fb_open,
+	.fb_release	= ps3fb_release,
+	.fb_check_var	= ps3fb_check_var,
+	.fb_set_par	= ps3fb_set_par,
+	.fb_setcolreg	= ps3fb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_mmap	= ps3fb_mmap,
+	.fb_blank	= ps3fb_blank,
+	.fb_ioctl	= ps3fb_ioctl,
+	.fb_compat_ioctl = ps3fb_ioctl
+};
+
+static struct fb_fix_screeninfo ps3fb_fix __initdata = {
+	.id =		"PS3 FB",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static int __init ps3fb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int retval = -ENOMEM;
+	u64 ddr_lpar = 0;
+	u64 lpar_dma_control = 0;
+	u64 lpar_driver_info = 0;
+	u64 lpar_reports = 0;
+	u64 lpar_reports_size = 0;
+	u64 xdr_lpar;
+	int status;
+	unsigned long offset;
+
+	/* get gpu context handle */
+	status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0,
+					 &ps3fb.memory_handle, &ddr_lpar);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n",
+		       __FUNCTION__, status);
+		goto err;
+	}
+	DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar);
+
+	status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
+					  &ps3fb.context_handle,
+					  &lpar_dma_control, &lpar_driver_info,
+					  &lpar_reports, &lpar_reports_size);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n",
+		       __FUNCTION__, status);
+		goto err_gpu_memory_free;
+	}
+
+	/* vsync interrupt */
+	ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);
+	if (!ps3fb.dinfo) {
+		printk(KERN_ERR "%s: ioremap failed\n", __FUNCTION__);
+		goto err_gpu_context_free;
+	}
+
+	retval = ps3fb_vsync_settings(ps3fb.dinfo, dev);
+	if (retval)
+		goto err_iounmap_dinfo;
+
+	/* xdr frame buffer */
+	ps3fb.xdr_ea = ps3fb_videomemory.address;
+	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea));
+	retval = ps3fb_xdr_settings(xdr_lpar);
+	if (retval)
+		goto err_free_irq;
+
+	/*
+	 * ps3fb must clear memory to prevent kernel info
+	 * leakage into userspace
+	 */
+	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	if (!info)
+		goto err_free_irq;
+
+	offset = FB_OFF(ps3fb.res_index) + VP_OFF(ps3fb.res_index);
+	info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;
+	info->fbops = &ps3fb_ops;
+
+	info->fix = ps3fb_fix;
+	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
+	info->fix.smem_len = ps3fb_videomemory.size - offset;
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err_framebuffer_release;
+
+	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
+			  ARRAY_SIZE(ps3fb_modedb), ps3fb_default_mode(), 32)) {
+		retval = -EINVAL;
+		goto err_fb_dealloc;
+	}
+
+	fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb),
+				 &info->modelist);
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err_fb_dealloc;
+
+	platform_set_drvdata(dev, info);
+
+	printk(KERN_INFO
+	       "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n",
+	       info->node, ps3fb_videomemory.size >> 10);
+
+	kernel_thread(ps3fbd, info, CLONE_KERNEL);
+	return 0;
+
+err_fb_dealloc:
+	fb_dealloc_cmap(&info->cmap);
+err_framebuffer_release:
+	framebuffer_release(info);
+err_free_irq:
+	free_irq(ps3fb.irq_no, ps3fb.dev);
+	ps3_free_irq(ps3fb.irq_no);
+err_iounmap_dinfo:
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+err_gpu_context_free:
+	lv1_gpu_context_free(ps3fb.context_handle);
+err_gpu_memory_free:
+	lv1_gpu_memory_free(ps3fb.memory_handle);
+err:
+	return retval;
+}
+
+static void ps3fb_shutdown(struct platform_device *dev)
+{
+	ps3fb_flip_ctl(0);	/* flip off */
+	ps3fb.dinfo->irq.mask = 0;
+	free_irq(ps3fb.irq_no, ps3fb.dev);
+	ps3_free_irq(ps3fb.irq_no);
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+}
+
+void ps3fb_cleanup(void)
+{
+	int status;
+
+	if (ps3fb.irq_no) {
+		free_irq(ps3fb.irq_no, ps3fb.dev);
+		ps3_free_irq(ps3fb.irq_no);
+	}
+	iounmap((u8 __iomem *)ps3fb.dinfo);
+
+	status = lv1_gpu_context_free(ps3fb.context_handle);
+	if (status)
+		DPRINTK("lv1_gpu_context_free failed: %d\n", status);
+
+	status = lv1_gpu_memory_free(ps3fb.memory_handle);
+	if (status)
+		DPRINTK("lv1_gpu_memory_free failed: %d\n", status);
+
+	ps3av_dev_close();
+}
+
+EXPORT_SYMBOL_GPL(ps3fb_cleanup);
+
+static int ps3fb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	ps3fb_cleanup();
+	return 0;
+}
+
+static struct platform_driver ps3fb_driver = {
+	.probe	= ps3fb_probe,
+	.remove = ps3fb_remove,
+	.shutdown = ps3fb_shutdown,
+	.driver = { .name = "ps3fb" }
+};
+
+static struct platform_device ps3fb_device = {
+	.name	= "ps3fb",
+	.id	= 0,
+	.dev	= { .release = ps3fb_platform_release }
+};
+
+int ps3fb_set_sync(void)
+{
+	int status;
+
+#ifdef HEAD_A
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n",
+		       __FUNCTION__, status);
+		return -1;
+	}
+#endif
+#ifdef HEAD_B
+	status = lv1_gpu_context_attribute(0x0,
+					   L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC,
+					   1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0);
+
+	if (status) {
+		printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n",
+		       __FUNCTION__, status);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ps3fb_set_sync);
+
+static int __init ps3fb_init(void)
+{
+	int error;
+#ifndef MODULE
+	int mode;
+	char *option = NULL;
+
+	if (fb_get_options("ps3fb", &option))
+		goto err;
+#endif
+
+	if (!ps3fb_videomemory.address)
+		goto err;
+
+	error = ps3av_dev_open();
+	if (error) {
+		printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__);
+		goto err;
+	}
+
+	ps3fb_mode = ps3av_get_mode();
+	DPRINTK("ps3av_mode:%d\n", ps3fb_mode);
+#ifndef MODULE
+	mode = ps3fb_setup(option);	/* check boot option */
+	if (mode)
+		ps3fb_mode = mode;
+#endif
+	if (ps3fb_mode > 0) {
+		u32 xres, yres;
+		ps3av_video_mode2res(ps3fb_mode, &xres, &yres);
+		ps3fb.res_index = ps3fb_get_res_table(xres, yres);
+		DPRINTK("res_index:%d\n", ps3fb.res_index);
+	} else
+		ps3fb.res_index = GPU_RES_INDEX;
+
+	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
+	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
+	init_MUTEX(&ps3fb.sem);
+	init_waitqueue_head(&ps3fb.wait_vsync);
+	ps3fb.num_frames = 1;
+
+	error = platform_driver_register(&ps3fb_driver);
+	if (!error) {
+		error = platform_device_register(&ps3fb_device);
+		if (error)
+			platform_driver_unregister(&ps3fb_driver);
+	}
+
+	ps3fb_set_sync();
+
+	return error;
+
+err:
+	return -ENXIO;
+}
+
+module_init(ps3fb_init);
+
+#ifdef MODULE
+static void __exit ps3fb_exit(void)
+{
+	platform_device_unregister(&ps3fb_device);
+	platform_driver_unregister(&ps3fb_driver);
+}
+
+module_exit(ps3fb_exit);
+
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c
deleted file mode 100644
index bc7ffc8..0000000
--- a/drivers/video/retz3fb.c
+++ /dev/null
@@ -1,1588 +0,0 @@
-/*
- * Linux/drivers/video/retz3fb.c -- RetinaZ3 frame buffer device
- *
- *    Copyright (C) 1997 Jes Sorensen
- *
- * This file is based on the CyberVision64 frame buffer device and
- * the generic Cirrus Logic driver.
- *
- * cyberfb.c: Copyright (C) 1996 Martin Apel,
- *                               Geert Uytterhoeven
- * clgen.c:   Copyright (C) 1996 Frank Neumann
- *
- * History:
- *   - 22 Jan 97: Initial work
- *   - 14 Feb 97: Screen initialization works somewhat, still only
- *                8-bit packed pixel is supported.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/zorro.h>
-#include <linux/init.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-
-#include "retz3fb.h"
-
-/* #define DEBUG if(1) */
-#define DEBUG if(0)
-
-/*
- * Reserve space for one pattern line.
- *
- * For the time being we only support 4MB boards!
- */
-
-#define PAT_MEM_SIZE 16*3
-#define PAT_MEM_OFF  (4*1024*1024 - PAT_MEM_SIZE)
-
-struct retz3fb_par {
-	int xres;
-	int yres;
-	int xres_vir;
-	int yres_vir;
-	int xoffset;
-	int yoffset;
-	int bpp;
-
-	struct fb_bitfield red;
-	struct fb_bitfield green;
-	struct fb_bitfield blue;
-	struct fb_bitfield transp;
-
-	int pixclock;
-	int left_margin;	/* time from sync to picture	*/
-	int right_margin;	/* time from picture to sync	*/
-	int upper_margin;	/* time from sync to picture	*/
-	int lower_margin;
-	int hsync_len;	/* length of horizontal sync	*/
-	int vsync_len;	/* length of vertical sync	*/
-	int vmode;
-
-	int accel;
-};
-
-struct display_data {
-	long h_total;		/* Horizontal Total */
-	long h_sstart;		/* Horizontal Sync Start */
-	long h_sstop;		/* Horizontal Sync Stop */
-	long h_bstart;		/* Horizontal Blank Start */
-	long h_bstop;		/* Horizontal Blank Stop */
-	long h_dispend;		/* Horizontal Display End */
-	long v_total;		/* Vertical Total */
-	long v_sstart;		/* Vertical Sync Start */
-	long v_sstop;		/* Vertical Sync Stop */
-	long v_bstart;		/* Vertical Blank Start */
-	long v_bstop;		/* Vertical Blank Stop */
-	long v_dispend;		/* Horizontal Display End */
-};
-
-struct retz3_fb_info {
-	struct fb_info info;
-	unsigned char *base;
-	unsigned char *fbmem;
-	unsigned long fbsize;
-	volatile unsigned char *regs;
-	unsigned long physfbmem;
-	unsigned long physregs;
-	int current_par_valid; /* set to 0 by memset */
-	int blitbusy;
-	struct display disp;
-	struct retz3fb_par current_par;
-	unsigned char color_table [256][3];
-};
-
-
-static char fontname[40] __initdata = { 0 };
-
-#define retz3info(info) ((struct retz3_fb_info *)(info))
-#define fbinfo(info) ((struct fb_info *)(info))
-
-
-/*
- *    Frame Buffer Name
- */
-
-static char retz3fb_name[16] = "RetinaZ3";
-
-
-/*
- * A small info on how to convert XFree86 timing values into fb
- * timings - by Frank Neumann:
- *
-An XFree86 mode line consists of the following fields:
- "800x600"     50      800  856  976 1040    600  637  643  666
- < name >     DCF       HR  SH1  SH2  HFL     VR  SV1  SV2  VFL
-
-The fields in the fb_var_screeninfo structure are:
-        unsigned long pixclock;         * pixel clock in ps (pico seconds) *
-        unsigned long left_margin;      * time from sync to picture    *
-        unsigned long right_margin;     * time from picture to sync    *
-        unsigned long upper_margin;     * time from sync to picture    *
-        unsigned long lower_margin;
-        unsigned long hsync_len;        * length of horizontal sync    *
-        unsigned long vsync_len;        * length of vertical sync      *
-
-1) Pixelclock:
-   xfree: in MHz
-   fb: In Picoseconds (ps)
-
-   pixclock = 1000000 / DCF
-
-2) horizontal timings:
-   left_margin = HFL - SH2
-   right_margin = SH1 - HR
-   hsync_len = SH2 - SH1
-
-3) vertical timings:
-   upper_margin = VFL - SV2
-   lower_margin = SV1 - VR
-   vsync_len = SV2 - SV1
-
-Good examples for VESA timings can be found in the XFree86 source tree,
-under "programs/Xserver/hw/xfree86/doc/modeDB.txt".
-*/
-
-/*
- *    Predefined Video Modes
- */
-
-static struct {
-    const char *name;
-    struct fb_var_screeninfo var;
-} retz3fb_predefined[] __initdata = {
-    /*
-     * NB: it is very important to adjust the pixel-clock to the color-depth.
-     */
-
-    {
-	"640x480", {		/* 640x480, 8 bpp */
-	    640, 480, 640, 480, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCEL_NONE, 39722, 48, 16, 33, 10, 96, 2,
-	    FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
-	}
-    },
-    /*
-     ModeLine "800x600" 36 800 824 896 1024 600 601 603 625
-	      < name > DCF HR  SH1 SH2  HFL VR  SV1 SV2 VFL
-     */
-    {
-	"800x600", {		/* 800x600, 8 bpp */
-	    800, 600, 800, 600, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 120, 2,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}
-    },
-    {
-	"800x600-60", {		/* 800x600, 8 bpp */
-	    800, 600, 800, 600, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 25000, 88, 40, 23, 1, 128, 4,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}
-    },
-    {
-	"800x600-70", {		/* 800x600, 8 bpp */
-	    800, 600, 800, 600, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 22272, 40, 24, 15, 9, 144, 12,
-	    FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED
-	}
-    },
-    /*
-      ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
-	       < name >   DCF HR  SH1  SH2  HFL  VR  SV1 SV2 VFL
-     */
-    {
-	"1024x768i", {		/* 1024x768, 8 bpp, interlaced */
-	    1024, 768, 1024, 768, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 22222, 40, 40, 32, 9, 160, 8,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED
-	}
-    },
-    {
-	"1024x768", {
-	    1024, 768, 1024, 768, 0, 0, 8, 0, 
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 
-	    0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
-	    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	 }
-    },
-    {
-	"640x480-16", {		/* 640x480, 16 bpp */
-	    640, 480, 640, 480, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, 0, 38461/2, 28, 32, 12, 10, 96, 2,
-	    FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
-	}
-    },
-    {
-	"640x480-24", {		/* 640x480, 24 bpp */
-	    640, 480, 640, 480, 0, 0, 24, 0,
-	    {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0},
-	    0, 0, -1, -1, 0, 38461/3, 28, 32, 12, 10, 96, 2,
-	    FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
-	}
-    },
-};
-
-
-#define NUM_TOTAL_MODES    ARRAY_SIZE(retz3fb_predefined)
-
-static struct fb_var_screeninfo retz3fb_default;
-
-static int z3fb_inverse = 0;
-static int z3fb_mode __initdata = 0;
-
-
-/*
- *    Interface used by the world
- */
-
-int retz3fb_setup(char *options);
-
-static int retz3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info);
-static int retz3fb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int retz3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info);
-static int retz3fb_setcolreg(unsigned int regno, unsigned int red,
-			     unsigned int green, unsigned int blue,
-			     unsigned int transp, struct fb_info *info);
-static int retz3fb_blank(int blank, struct fb_info *info);
-
-
-/*
- *    Interface to the low level console driver
- */
-
-int retz3fb_init(void);
-static int z3fb_switch(int con, struct fb_info *info);
-static int z3fb_updatevar(int con, struct fb_info *info);
-
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static struct display_switch fbcon_retz3_8;
-#endif
-
-
-/*
- *    Accelerated Functions used by the low level console driver
- */
-
-static void retz3_bitblt(struct display *p,
-			 unsigned short curx, unsigned short cury, unsigned
-			 short destx, unsigned short desty, unsigned short
-			 width, unsigned short height, unsigned short cmd,
-			 unsigned short mask);
-
-/*
- *   Hardware Specific Routines
- */
-
-static int retz3_encode_fix(struct fb_info *info,
-			    struct fb_fix_screeninfo *fix,
-			    struct retz3fb_par *par);
-static int retz3_decode_var(struct fb_var_screeninfo *var,
-			    struct retz3fb_par *par);
-static int retz3_encode_var(struct fb_var_screeninfo *var,
-			    struct retz3fb_par *par);
-static int retz3_getcolreg(unsigned int regno, unsigned int *red,
-			   unsigned int *green, unsigned int *blue,
-			   unsigned int *transp, struct fb_info *info);
-
-/*
- *    Internal routines
- */
-
-static void retz3fb_get_par(struct fb_info *info, struct retz3fb_par *par);
-static void retz3fb_set_par(struct fb_info *info, struct retz3fb_par *par);
-static int do_fb_set_var(struct fb_info *info,
-			 struct fb_var_screeninfo *var, int isactive);
-static void retz3fb_set_disp(int con, struct fb_info *info);
-static int get_video_mode(const char *name);
-
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-static unsigned short find_fq(unsigned int freq)
-{
-	unsigned long f;
-	long tmp;
-	long prev = 0x7fffffff;
-	long n2, n1 = 3;
-	unsigned long m;
-	unsigned short res = 0;
-
-	if (freq <= 31250000)
-		n2 = 3;
-	else if (freq <= 62500000)
-		n2 = 2;
-	else if (freq <= 125000000)
-		n2 = 1;
-	else if (freq <= 250000000)
-		n2 = 0;
-	else
-		return 0;
-
-
-	do {
-		f = freq >> (10 - n2);
-
-		m = (f * n1) / (14318180/1024);
-
-		if (m > 129)
-			break;
-
-		tmp =  (((m * 14318180) >> n2) / n1) - freq;
-		if (tmp < 0)
-			tmp = -tmp;
-
-		if (tmp < prev) {
-			prev = tmp;
-			res = (((n2 << 5) | (n1-2)) << 8) | (m-2);
-		}
-
-	} while ( (++n1) <= 21);
-
-	return res;
-}
-
-
-static int retz3_set_video(struct fb_info *info,
-			   struct fb_var_screeninfo *var,
-			   struct retz3fb_par *par)
-{
-	volatile unsigned char *regs = retz3info(info)->regs;
-	unsigned int freq;
-
-	int xres, hfront, hsync, hback;
-	int yres, vfront, vsync, vback;
-	unsigned char tmp;
-	unsigned short best_freq;
-	struct display_data data;
-
-	short clocksel = 0; /* Apparantly this is always zero */
-
-	int bpp = var->bits_per_pixel;
-
-	/*
-	 * XXX
-	 */
-	if (bpp == 24)
-		return 0;
-
-	if ((bpp != 8) && (bpp != 16) && (bpp != 24))
-		return -EFAULT;
-
-	par->xoffset = 0;
-	par->yoffset = 0;
-
-	xres   = var->xres * bpp / 4;
-	hfront = var->right_margin * bpp / 4;
-	hsync  = var->hsync_len * bpp / 4;
-	hback  = var->left_margin * bpp / 4;
-
-	if (var->vmode & FB_VMODE_DOUBLE)
-	{
-		yres = var->yres * 2;
-		vfront = var->lower_margin * 2;
-		vsync  = var->vsync_len * 2;
-		vback  = var->upper_margin * 2;
-	}
-	else if (var->vmode & FB_VMODE_INTERLACED)
-	{
-		yres   = (var->yres + 1) / 2;
-		vfront = (var->lower_margin + 1) / 2;
-		vsync  = (var->vsync_len + 1) / 2;
-		vback  = (var->upper_margin + 1) / 2;
-	}
-	else
-	{
-		yres   = var->yres; /* -1 ? */
-		vfront = var->lower_margin;
-		vsync  = var->vsync_len;
-		vback  = var->upper_margin;
-	}
-
-	data.h_total	= (hback / 8) + (xres / 8)
-			+ (hfront / 8) + (hsync / 8) - 1 /* + 1 */;
-	data.h_dispend	= ((xres + bpp - 1)/ 8) - 1;
-	data.h_bstart	= xres / 8 - 1 /* + 1 */;
-
-	data.h_bstop	= data.h_total+1 + 2 + 1;
-	data.h_sstart	= (xres / 8) + (hfront / 8) + 1;
-	data.h_sstop	= (xres / 8) + (hfront / 8) + (hsync / 8) + 1;
-
-	data.v_total	= yres + vfront + vsync + vback - 1;
-
-	data.v_dispend	= yres - 1;
-	data.v_bstart	= yres - 1;
-
-	data.v_bstop	= data.v_total;
-	data.v_sstart	= yres + vfront - 1 - 2;
-	data.v_sstop	= yres + vfront + vsync - 1;
-
-#if 0 /* testing */
-
-	printk("HBS: %i\n", data.h_bstart);
-	printk("HSS: %i\n", data.h_sstart);
-	printk("HSE: %i\n", data.h_sstop);
-	printk("HBE: %i\n", data.h_bstop);
-	printk("HT: %i\n", data.h_total);
-
-	printk("hsync: %i\n", hsync);
-	printk("hfront: %i\n", hfront);
-	printk("hback: %i\n", hback);
-
-	printk("VBS: %i\n", data.v_bstart);
-	printk("VSS: %i\n", data.v_sstart);
-	printk("VSE: %i\n", data.v_sstop);
-	printk("VBE: %i\n", data.v_bstop);
-	printk("VT: %i\n", data.v_total);
-
-	printk("vsync: %i\n", vsync);
-	printk("vfront: %i\n", vfront);
-	printk("vback: %i\n", vback);
-#endif
-
-	if (data.v_total >= 1024)
-		printk(KERN_ERR "MAYDAY: v_total >= 1024; bailing out!\n");
-
-	reg_w(regs, GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
-	reg_w(regs, GREG_FEATURE_CONTROL_W, 0x00);
-
-	seq_w(regs, SEQ_RESET, 0x00);
-	seq_w(regs, SEQ_RESET, 0x03);	/* reset sequencer logic */
-
-	/*
-	 * CLOCKING_MODE bits:
-	 * 2: This one is only set for certain text-modes, wonder if
-	 *    it may be for EGA-lines? (it was referred to as CLKDIV2)
-	 * (The CL drivers sets it to 0x21 with the comment:
-	 *  FullBandwidth (video off) and 8/9 dot clock)
-	 */
-	seq_w(regs, SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */);
-
-	seq_w(regs, SEQ_MAP_MASK, 0x0f);        /* enable writing to plane 0-3 */
-	seq_w(regs, SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */
-	seq_w(regs, SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/
-	seq_w(regs, SEQ_RESET, 0x01);
-	seq_w(regs, SEQ_RESET, 0x03);
-
-	seq_w(regs, SEQ_EXTENDED_ENABLE, 0x05);
-
-	seq_w(regs, SEQ_CURSOR_CONTROL, 0x00);	/* disable cursor */
-	seq_w(regs, SEQ_PRIM_HOST_OFF_HI, 0x00);
-	seq_w(regs, SEQ_PRIM_HOST_OFF_HI, 0x00);
-	seq_w(regs, SEQ_LINEAR_0, 0x4a);
-	seq_w(regs, SEQ_LINEAR_1, 0x00);
-
-	seq_w(regs, SEQ_SEC_HOST_OFF_HI, 0x00);
-	seq_w(regs, SEQ_SEC_HOST_OFF_LO, 0x00);
-	seq_w(regs, SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
-
-	/*
-	 * The lower 4 bits (0-3) are used to set the font-width for
-	 * text-mode - DON'T try to set this for gfx-mode.
-	 */
-	seq_w(regs, SEQ_EXT_CLOCK_MODE, 0x10);
-	seq_w(regs, SEQ_EXT_VIDEO_ADDR, 0x03);
-
-	/*
-	 * Extended Pixel Control:
-	 * bit 0:   text-mode=0, gfx-mode=1 (Graphics Byte ?)
-	 * bit 1: (Packed/Nibble Pixel Format ?)
-	 * bit 4-5: depth, 0=1-8bpp, 1=9-16bpp, 2=17-24bpp
-	 */
-	seq_w(regs, SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4));
-
-	seq_w(regs, SEQ_BUS_WIDTH_FEEDB, 0x04);
-	seq_w(regs, SEQ_COLOR_EXP_WFG, 0x01);
-	seq_w(regs, SEQ_COLOR_EXP_WBG, 0x00);
-	seq_w(regs, SEQ_EXT_RW_CONTROL, 0x00);
-	seq_w(regs, SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8)));
-	seq_w(regs, SEQ_COLOR_KEY_CNTL, 0x40);
-	seq_w(regs, SEQ_COLOR_KEY_MATCH0, 0x00);
-	seq_w(regs, SEQ_COLOR_KEY_MATCH1, 0x00);
-	seq_w(regs, SEQ_COLOR_KEY_MATCH2, 0x00);
-	seq_w(regs, SEQ_CRC_CONTROL, 0x00);
-	seq_w(regs, SEQ_PERF_SELECT, 0x10);
-	seq_w(regs, SEQ_ACM_APERTURE_1, 0x00);
-	seq_w(regs, SEQ_ACM_APERTURE_2, 0x30);
-	seq_w(regs, SEQ_ACM_APERTURE_3, 0x00);
-	seq_w(regs, SEQ_MEMORY_MAP_CNTL, 0x03);
-
-
-	/* unlock register CRT0..CRT7 */
-	crt_w(regs, CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20);
-
-	/* Zuerst zu schreibende Werte nur per printk ausgeben */
-	DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total);
-	crt_w(regs, CRT_HOR_TOTAL, data.h_total & 0xff);
-
-	DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend);
-	crt_w(regs, CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff);
-
-	DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart);
-	crt_w(regs, CRT_START_HOR_BLANK, data.h_bstart & 0xff);
-
-	DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32);
-	crt_w(regs, CRT_END_HOR_BLANK,  0x80 | (data.h_bstop & 0x1f));
-
-	DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart);
-	crt_w(regs, CRT_START_HOR_RETR, data.h_sstart & 0xff);
-
-	tmp = (data.h_sstop & 0x1f);
-	if (data.h_bstop & 0x20)
-		tmp |= 0x80;
-	DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp);
-	crt_w(regs, CRT_END_HOR_RETR, tmp);
-
-	DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff);
-	crt_w(regs, CRT_VER_TOTAL, (data.v_total & 0xff));
-
-	tmp = 0x10;  /* LineCompare bit #9 */
-	if (data.v_total & 256)
-		tmp |= 0x01;
-	if (data.v_dispend & 256)
-		tmp |= 0x02;
-	if (data.v_sstart & 256)
-		tmp |= 0x04;
-	if (data.v_bstart & 256)
-		tmp |= 0x08;
-	if (data.v_total & 512)
-		tmp |= 0x20;
-	if (data.v_dispend & 512)
-		tmp |= 0x40;
-	if (data.v_sstart & 512)
-		tmp |= 0x80;
-	DEBUG printk("CRT_OVERFLOW: %d\n", tmp);
-	crt_w(regs, CRT_OVERFLOW, tmp);
-
-	crt_w(regs, CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */
-
-	tmp = 0x40; /* LineCompare bit #8 */
-	if (data.v_bstart & 512)
-		tmp |= 0x20;
-	if (var->vmode & FB_VMODE_DOUBLE)
-		tmp |= 0x80;
- 	DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp);
-	crt_w(regs, CRT_MAX_SCAN_LINE, tmp);
-
-	crt_w(regs, CRT_CURSOR_START, 0x00);
-	crt_w(regs, CRT_CURSOR_END, 8 & 0x1f); /* font height */
-
-	crt_w(regs, CRT_START_ADDR_HIGH, 0x00);
-	crt_w(regs, CRT_START_ADDR_LOW, 0x00);
-
-	crt_w(regs, CRT_CURSOR_LOC_HIGH, 0x00);
-	crt_w(regs, CRT_CURSOR_LOC_LOW, 0x00);
-
- 	DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff);
-	crt_w(regs, CRT_START_VER_RETR, (data.v_sstart & 0xff));
-
-#if 1
-	/* 5 refresh cycles per scanline */
-	DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16);
-	crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));
-#else
-	DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16);
-	crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));
-#endif
-	DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff);
-	crt_w(regs, CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff));
-
-	DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff);
-	crt_w(regs, CRT_START_VER_BLANK, (data.v_bstart & 0xff));
-
-	DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff);
-	crt_w(regs, CRT_END_VER_BLANK, (data.v_bstop & 0xff));
-
-	DEBUG printk("CRT_MODE_CONTROL: 0xe3\n");
-	crt_w(regs, CRT_MODE_CONTROL, 0xe3);
-
-	DEBUG printk("CRT_LINE_COMPARE: 0xff\n");
-	crt_w(regs, CRT_LINE_COMPARE, 0xff);
-
-	tmp = (var->xres_virtual / 8) * (bpp / 8);
-	crt_w(regs, CRT_OFFSET, tmp);
-
-	crt_w(regs, CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */
-
-	tmp = 0x20;			/* Enable extended end bits */
-	if (data.h_total & 0x100)
-		tmp |= 0x01;
-	if ((data.h_dispend) & 0x100)
-		tmp |= 0x02;
-	if (data.h_bstart & 0x100)
-		tmp |= 0x04;
-	if (data.h_sstart & 0x100)
-		tmp |= 0x08;
-	if (var->vmode & FB_VMODE_INTERLACED)
-		tmp |= 0x10;
- 	DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp);
-	crt_w(regs, CRT_EXT_HOR_TIMING1, tmp);
-
-	tmp = 0x00;
-	if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100)
-		tmp |= 0x10;
-	crt_w(regs, CRT_EXT_START_ADDR, tmp);
-
-	tmp = 0x00;
-	if (data.h_total & 0x200)
-		tmp |= 0x01;
-	if ((data.h_dispend) & 0x200)
-		tmp |= 0x02;
-	if (data.h_bstart & 0x200)
-		tmp |= 0x04;
-	if (data.h_sstart & 0x200)
-		tmp |= 0x08;
-	tmp |= ((data.h_bstop & 0xc0) >> 2);
-	tmp |= ((data.h_sstop & 0x60) << 1);
-	crt_w(regs, CRT_EXT_HOR_TIMING2, tmp);
- 	DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp);
-
-	tmp = 0x10;			/* Line compare bit 10 */
-	if (data.v_total & 0x400)
-		tmp |= 0x01;
-	if ((data.v_dispend) & 0x400)
-		tmp |= 0x02;
-	if (data.v_bstart & 0x400)
-		tmp |= 0x04;
-	if (data.v_sstart & 0x400)
-		tmp |= 0x08;
-	tmp |= ((data.v_bstop & 0x300) >> 3);
-	if (data.v_sstop & 0x10)
-		tmp |= 0x80;
-	crt_w(regs, CRT_EXT_VER_TIMING, tmp);
- 	DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp);
-
-	crt_w(regs, CRT_MONITOR_POWER, 0x00);
-
-	/*
-	 * Convert from ps to Hz.
-	 */
-	freq = 2000000000 / var->pixclock;
-	freq = freq * 500;
-
-	best_freq = find_fq(freq);
-	pll_w(regs, 0x02, best_freq);
-	best_freq = find_fq(61000000);
-	pll_w(regs, 0x0a, best_freq);
-	pll_w(regs, 0x0e, 0x22);
-
-	gfx_w(regs, GFX_SET_RESET, 0x00);
-	gfx_w(regs, GFX_ENABLE_SET_RESET, 0x00);
-	gfx_w(regs, GFX_COLOR_COMPARE, 0x00);
-	gfx_w(regs, GFX_DATA_ROTATE, 0x00);
-	gfx_w(regs, GFX_READ_MAP_SELECT, 0x00);
-	gfx_w(regs, GFX_GRAPHICS_MODE, 0x00);
-	gfx_w(regs, GFX_MISC, 0x05);
-	gfx_w(regs, GFX_COLOR_XCARE, 0x0f);
-	gfx_w(regs, GFX_BITMASK, 0xff);
-
-	reg_r(regs, ACT_ADDRESS_RESET);
-	attr_w(regs, ACT_PALETTE0 , 0x00);
-	attr_w(regs, ACT_PALETTE1 , 0x01);
-	attr_w(regs, ACT_PALETTE2 , 0x02);
-	attr_w(regs, ACT_PALETTE3 , 0x03);
-	attr_w(regs, ACT_PALETTE4 , 0x04);
-	attr_w(regs, ACT_PALETTE5 , 0x05);
-	attr_w(regs, ACT_PALETTE6 , 0x06);
-	attr_w(regs, ACT_PALETTE7 , 0x07);
-	attr_w(regs, ACT_PALETTE8 , 0x08);
-	attr_w(regs, ACT_PALETTE9 , 0x09);
-	attr_w(regs, ACT_PALETTE10, 0x0a);
-	attr_w(regs, ACT_PALETTE11, 0x0b);
-	attr_w(regs, ACT_PALETTE12, 0x0c);
-	attr_w(regs, ACT_PALETTE13, 0x0d);
-	attr_w(regs, ACT_PALETTE14, 0x0e);
-	attr_w(regs, ACT_PALETTE15, 0x0f);
-	reg_r(regs, ACT_ADDRESS_RESET);
-
-	attr_w(regs, ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */
-
-	attr_w(regs, ACT_OVERSCAN_COLOR, 0x00);
-	attr_w(regs, ACT_COLOR_PLANE_ENA, 0x0f);
-	attr_w(regs, ACT_HOR_PEL_PANNING, 0x00);
-	attr_w(regs, ACT_COLOR_SELECT, 0x00);
-
-	reg_r(regs, ACT_ADDRESS_RESET);
-	reg_w(regs, ACT_DATA, 0x20);
-
-	reg_w(regs, VDAC_MASK, 0xff);
-
-	/*
-	 * Extended palette addressing ???
-	 */
-	switch (bpp){
-	case 8:
-		reg_w(regs, 0x83c6, 0x00);
-		break;
-	case 16:
-		reg_w(regs, 0x83c6, 0x60);
-		break;
-	case 24:
-		reg_w(regs, 0x83c6, 0xe0);
-		break;
-	default:
-		printk(KERN_INFO "Illegal color-depth: %i\n", bpp);
-	}
-
-	reg_w(regs, VDAC_ADDRESS, 0x00);
-
-	seq_w(regs, SEQ_MAP_MASK, 0x0f );
-
-	return 0;
-}
-
-
-/*
- *    This function should fill in the `fix' structure based on the
- *    values in the `par' structure.
- */
-
-static int retz3_encode_fix(struct fb_info *info,
-			    struct fb_fix_screeninfo *fix,
-			    struct retz3fb_par *par)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, retz3fb_name);
-	fix->smem_start = zinfo->physfbmem;
-	fix->smem_len = zinfo->fbsize;
-	fix->mmio_start = zinfo->physregs;
-	fix->mmio_len = 0x00c00000;
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-	if (par->bpp == 8)
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-		fix->visual = FB_VISUAL_TRUECOLOR;
-
-	fix->xpanstep = 0;
-	fix->ypanstep = 0;
-	fix->ywrapstep = 0;
-	fix->line_length = 0;
-
-	fix->accel = FB_ACCEL_NCR_77C32BLT;
-
-	return 0;
-}
-
-
-/*
- *    Get the video params out of `var'. If a value doesn't fit, round
- *    it up, if it's too big, return -EINVAL.
- */
-
-static int retz3_decode_var(struct fb_var_screeninfo *var,
-			    struct retz3fb_par *par)
-{
-	par->xres = var->xres;
-	par->yres = var->yres;
-	par->xres_vir = var->xres_virtual;
-	par->yres_vir = var->yres_virtual;
-	par->bpp = var->bits_per_pixel;
-	par->pixclock = var->pixclock;
-	par->vmode = var->vmode;
-
-	par->red = var->red;
-	par->green = var->green;
-	par->blue = var->blue;
-	par->transp = var->transp;
-
-	par->left_margin = var->left_margin;
-	par->right_margin = var->right_margin;
-	par->upper_margin = var->upper_margin;
-	par->lower_margin = var->lower_margin;
-	par->hsync_len = var->hsync_len;
-	par->vsync_len = var->vsync_len;
-
-	if (var->accel_flags & FB_ACCELF_TEXT)
-	    par->accel = FB_ACCELF_TEXT;
-	else
-	    par->accel = 0;
-
-	return 0;
-}
-
-
-/*
- *    Fill the `var' structure based on the values in `par' and maybe
- *    other values read out of the hardware.
- */
-
-static int retz3_encode_var(struct fb_var_screeninfo *var,
-			    struct retz3fb_par *par)
-{
-	memset(var, 0, sizeof(struct fb_var_screeninfo));
-	var->xres = par->xres;
-	var->yres = par->yres;
-	var->xres_virtual = par->xres_vir;
-	var->yres_virtual = par->yres_vir;
-	var->xoffset = 0;
-	var->yoffset = 0;
-
-	var->bits_per_pixel = par->bpp;
-	var->grayscale = 0;
-
-	var->red = par->red;
-	var->green = par->green;
-	var->blue = par->blue;
-	var->transp = par->transp;
-
-	var->nonstd = 0;
-	var->activate = 0;
-
-	var->height = -1;
-	var->width = -1;
-
-	var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0;
-
-	var->pixclock = par->pixclock;
-
-	var->sync = 0;				/* ??? */
-	var->left_margin = par->left_margin;
-	var->right_margin = par->right_margin;
-	var->upper_margin = par->upper_margin;
-	var->lower_margin = par->lower_margin;
-	var->hsync_len = par->hsync_len;
-	var->vsync_len = par->vsync_len;
-
-	var->vmode = par->vmode;
-	return 0;
-}
-
-
-/*
- *    Set a single color register. Return != 0 for invalid regno.
- */
-
-static int retz3fb_setcolreg(unsigned int regno, unsigned int red,
-			     unsigned int green, unsigned int blue,
-			     unsigned int transp, struct fb_info *info)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-	volatile unsigned char *regs = zinfo->regs;
-
-	/* We'll get to this */
-
-	if (regno > 255)
-		return 1;
-
-	red >>= 10;
-	green >>= 10;
-	blue >>= 10;
-
-	zinfo->color_table[regno][0] = red;
-	zinfo->color_table[regno][1] = green;
-	zinfo->color_table[regno][2] = blue;
-
-	reg_w(regs, VDAC_ADDRESS_W, regno);
-	reg_w(regs, VDAC_DATA, red);
-	reg_w(regs, VDAC_DATA, green);
-	reg_w(regs, VDAC_DATA, blue);
-
-	return 0;
-}
-
-
-/*
- *    Read a single color register and split it into
- *    colors/transparent. Return != 0 for invalid regno.
- */
-
-static int retz3_getcolreg(unsigned int regno, unsigned int *red,
-			   unsigned int *green, unsigned int *blue,
-			   unsigned int *transp, struct fb_info *info)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-	int t;
-
-	if (regno > 255)
-		return 1;
-	t       = zinfo->color_table[regno][0];
-	*red    = (t<<10) | (t<<4) | (t>>2);
-	t       = zinfo->color_table[regno][1];
-	*green  = (t<<10) | (t<<4) | (t>>2);
-	t       = zinfo->color_table[regno][2];
-	*blue   = (t<<10) | (t<<4) | (t>>2);
-	*transp = 0;
-	return 0;
-}
-
-
-static inline void retz3_busy(struct display *p)
-{
-	struct retz3_fb_info *zinfo = retz3info(p->fb_info);
-	volatile unsigned char *acm = zinfo->base + ACM_OFFSET;
-	unsigned char blt_status;
-
-	if (zinfo->blitbusy) {
-		do{
-			blt_status = *((acm) + (ACM_START_STATUS + 2));
-		}while ((blt_status & 1) == 0);
-		zinfo->blitbusy = 0;
-	}
-}
-
-
-static void retz3_bitblt (struct display *p,
-			  unsigned short srcx, unsigned short srcy,
-			  unsigned short destx, unsigned short desty,
-			  unsigned short width, unsigned short height,
-			  unsigned short cmd, unsigned short mask)
-{
-	struct fb_var_screeninfo *var = &p->var;
-	struct retz3_fb_info *zinfo = retz3info(p->fb_info);
-	volatile unsigned long *acm = (unsigned long *)(zinfo->base + ACM_OFFSET);
-	unsigned long *pattern = (unsigned long *)(zinfo->fbmem + PAT_MEM_OFF);
-
-	unsigned short mod;
-	unsigned long tmp;
-	unsigned long pat, src, dst;
-
-	int i, xres_virtual = var->xres_virtual;
-	short bpp = (var->bits_per_pixel & 0xff);
-
-	if (bpp < 8)
-		bpp = 8;
-
-	tmp = mask | (mask << 16);
-
-	retz3_busy(p);
-
-	i = 0;
-	do{
-		*pattern++ = tmp;
-	}while(i++ < bpp/4);
-
-	tmp = cmd << 8;
-	*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
-
-	mod = 0xc0c2;
-
-	pat = 8 * PAT_MEM_OFF;
-	dst = bpp * (destx + desty * xres_virtual);
-
-	/*
-	 * Source is not set for clear.
-	 */
-	if ((cmd != Z3BLTclear) && (cmd != Z3BLTset)) {
-		src = bpp * (srcx + srcy * xres_virtual);
-
-		if (destx > srcx) {
-			mod &= ~0x8000;
-			src += bpp * (width - 1);
-			dst += bpp * (width - 1);
-			pat += bpp * 2;
-		}
-		if (desty > srcy) {
-			mod &= ~0x4000;
-			src += bpp * (height - 1) * xres_virtual;
-			dst += bpp * (height - 1) * xres_virtual;
-			pat += bpp * 4;
-		}
-
-		*(acm + ACM_SOURCE/4) = cpu_to_le32(src);
-	}
-
-	*(acm + ACM_PATTERN/4) = cpu_to_le32(pat);
-
-	*(acm + ACM_DESTINATION/4) = cpu_to_le32(dst);
-
-	tmp = mod << 16;
-	*(acm + ACM_CONTROL/4) = tmp;
-
-	tmp  = width | (height << 16);
-
-	*(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp);
-
-	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
-	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
-	zinfo->blitbusy = 1;
-}
-
-#if 0
-/*
- * Move cursor to x, y
- */
-static void retz3_MoveCursor (unsigned short x, unsigned short y)
-{
-	/* Guess we gotta deal with the cursor at some point */
-}
-#endif
-
-
-/*
- *    Fill the hardware's `par' structure.
- */
-
-static void retz3fb_get_par(struct fb_info *info, struct retz3fb_par *par)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	if (zinfo->current_par_valid)
-		*par = zinfo->current_par;
-	else
-		retz3_decode_var(&retz3fb_default, par);
-}
-
-
-static void retz3fb_set_par(struct fb_info *info, struct retz3fb_par *par)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	zinfo->current_par = *par;
-	zinfo->current_par_valid = 1;
-}
-
-
-static int do_fb_set_var(struct fb_info *info,
-			 struct fb_var_screeninfo *var, int isactive)
-{
-	int err, activate;
-	struct retz3fb_par par;
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	if ((err = retz3_decode_var(var, &par)))
-		return err;
-	activate = var->activate;
-
-	/* XXX ... what to do about isactive ? */
-
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
-		retz3fb_set_par(info, &par);
-	retz3_encode_var(var, &par);
-	var->activate = activate;
-
-	retz3_set_video(info, var, &zinfo->current_par);
-
-	return 0;
-}
-
-/*
- *    Get the Fixed Part of the Display
- */
-
-static int retz3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info)
-{
-	struct retz3fb_par par;
-	int error = 0;
-
-	if (con == -1)
-		retz3fb_get_par(info, &par);
-	else
-		error = retz3_decode_var(&fb_display[con].var, &par);
-	return(error ? error : retz3_encode_fix(info, fix, &par));
-}
-
-
-/*
- *    Get the User Defined Part of the Display
- */
-
-static int retz3fb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	struct retz3fb_par par;
-	int error = 0;
-
-	if (con == -1) {
-		retz3fb_get_par(info, &par);
-		error = retz3_encode_var(var, &par);
-	} else
-		*var = fb_display[con].var;
-	return error;
-}
-
-
-static void retz3fb_set_disp(int con, struct fb_info *info)
-{
-	struct fb_fix_screeninfo fix;
-	struct display *display;
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &zinfo->disp;	/* used during initialization */
-
-	retz3fb_get_fix(&fix, con, info);
-
-	if (con == -1)
-		con = 0;
-
-	display->visual = fix.visual;
-	display->type = fix.type;
-	display->type_aux = fix.type_aux;
-	display->ypanstep = fix.ypanstep;
-	display->ywrapstep = fix.ywrapstep;
-	display->can_soft_blank = 1;
-	display->inverse = z3fb_inverse;
-
-	/*
-	 * This seems to be about 20% faster.
-	 */
-	display->scrollmode = SCROLL_YREDRAW;
-
-	switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		if (display->var.accel_flags & FB_ACCELF_TEXT) {
-		    display->dispsw = &fbcon_retz3_8;
-		    retz3_set_video(info, &display->var, &zinfo->current_par);
-		} else
-		    display->dispsw = &fbcon_cfb8;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	case 16:
-		display->dispsw = &fbcon_cfb16;
-		break;
-#endif
-	default:
-		display->dispsw = &fbcon_dummy;
-		break;
-	}
-}
-
-
-/*
- *    Set the User Defined Part of the Display
- */
-
-static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
-	struct display *display;
-	struct retz3_fb_info *zinfo = retz3info(info);
-
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &zinfo->disp;	/* used during initialization */
-
-	if ((err = do_fb_set_var(info, var, con == info->currcon)))
-		return err;
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-		oldxres = display->var.xres;
-		oldyres = display->var.yres;
-		oldvxres = display->var.xres_virtual;
-		oldvyres = display->var.yres_virtual;
-		oldbpp = display->var.bits_per_pixel;
-		oldaccel = display->var.accel_flags;
-		display->var = *var;
-
-		if (oldxres != var->xres || oldyres != var->yres ||
-		    oldvxres != var->xres_virtual ||
-		    oldvyres != var->yres_virtual ||
-		    oldbpp != var->bits_per_pixel ||
-		    oldaccel != var->accel_flags) {
-
-			struct fb_fix_screeninfo fix;
-			retz3fb_get_fix(&fix, con, info);
-
-			display->visual = fix.visual;
-			display->type = fix.type;
-			display->type_aux = fix.type_aux;
-			display->ypanstep = fix.ypanstep;
-			display->ywrapstep = fix.ywrapstep;
-			display->line_length = fix.line_length;
-			display->can_soft_blank = 1;
-			display->inverse = z3fb_inverse;
-			switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-			case 8:
-				if (var->accel_flags & FB_ACCELF_TEXT) {
-					display->dispsw = &fbcon_retz3_8;
-				} else
-					display->dispsw = &fbcon_cfb8;
-				break;
-#endif
-#ifdef FBCON_HAS_CFB16
-			case 16:
-				display->dispsw = &fbcon_cfb16;
-				break;
-#endif
-			default:
-				display->dispsw = &fbcon_dummy;
-				break;
-			}
-			/*
-			 * We still need to find a way to tell the X
-			 * server that the video mem has been fiddled with
-			 * so it redraws the entire screen when switching
-			 * between X and a text console.
-			 */
-			retz3_set_video(info, var, &zinfo->current_par);
-
-			if (info->changevar)
-				(*info->changevar)(con);
-		}
-
-		if (oldbpp != var->bits_per_pixel) {
-			if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
-				return err;
-			do_install_cmap(con, info);
-		}
-	}
-	return 0;
-}
-
-
-/*
- *    Get the Colormap
- */
-
-static int retz3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info)
-{
-	if (con == info->currcon) /* current console? */
-		return(fb_get_cmap(cmap, kspc, retz3_getcolreg, info));
-	else if (fb_display[con].cmap.len) /* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-			     cmap, kspc ? 0 : 2);
-	return 0;
-}
-
-/*
- *    Blank the display.
- */
-
-static int retz3fb_blank(int blank, struct fb_info *info)
-{
-	struct retz3_fb_info *zinfo = retz3info(info);
-	volatile unsigned char *regs = retz3info(info)->regs;
-	short i;
-
-	if (blank)
-		for (i = 0; i < 256; i++){
-			reg_w(regs, VDAC_ADDRESS_W, i);
-			reg_w(regs, VDAC_DATA, 0);
-			reg_w(regs, VDAC_DATA, 0);
-			reg_w(regs, VDAC_DATA, 0);
-		}
-	else
-		for (i = 0; i < 256; i++){
-			reg_w(regs, VDAC_ADDRESS_W, i);
-			reg_w(regs, VDAC_DATA, zinfo->color_table[i][0]);
-			reg_w(regs, VDAC_DATA, zinfo->color_table[i][1]);
-			reg_w(regs, VDAC_DATA, zinfo->color_table[i][2]);
-		}
-	return 0;
-}
-
-static struct fb_ops retz3fb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	retz3fb_get_fix,
-	.fb_get_var =	retz3fb_get_var,
-	.fb_set_var =	retz3fb_set_var,
-	.fb_get_cmap =	retz3fb_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	retz3fb_setcolreg,
-	.fb_blank =	retz3fb_blank,
-};
-
-int __init retz3fb_setup(char *options)
-{
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "inverse")) {
-			z3fb_inverse = 1;
-			fb_invert_cmaps();
-		} else if (!strncmp(this_opt, "font:", 5)) {
-			strlcpy(fontname, this_opt+5, sizeof(fontname));
-		} else
-			z3fb_mode = get_video_mode(this_opt);
-	}
-	return 0;
-}
-
-
-/*
- *    Initialization
- */
-
-int __init retz3fb_init(void)
-{
-	unsigned long board_addr, board_size;
-	struct zorro_dev *z = NULL;
-	volatile unsigned char *regs;
-	struct retz3fb_par par;
-	struct retz3_fb_info *zinfo;
-	struct fb_info *fb_info;
-	short i;
-	int res = -ENXIO;
-
-	while ((z = zorro_find_device(ZORRO_PROD_MACROSYSTEMS_RETINA_Z3, z))) {
-		board_addr = z->resource.start;
-		board_size = z->resource.end-z->resource.start+1;
-		if (!request_mem_region(board_addr, 0x0c00000,
-			    		"ncr77c32blt")) {
-			continue;
-		if (!request_mem_region(board_addr+VIDEO_MEM_OFFSET,
-			    		0x00400000, "RAM"))
-			release_mem_region(board_addr, 0x00c00000);
-			continue;
-		}
-		if (!(zinfo = kmalloc(sizeof(struct retz3_fb_info),
-				      GFP_KERNEL)))
-			return -ENOMEM;
-		memset(zinfo, 0, sizeof(struct retz3_fb_info));
-
-		zinfo->base = ioremap(board_addr, board_size);
-		zinfo->regs = zinfo->base;
-		zinfo->fbmem = zinfo->base + VIDEO_MEM_OFFSET;
-		/* Get memory size - for now we asume it's a 4MB board */
-		zinfo->fbsize = 0x00400000; /* 4 MB */
-		zinfo->physregs = board_addr;
-		zinfo->physfbmem = board_addr + VIDEO_MEM_OFFSET;
-
-		fb_info = fbinfo(zinfo);
-
-		for (i = 0; i < 256; i++){
-			for (i = 0; i < 256; i++){
-				zinfo->color_table[i][0] = i;
-				zinfo->color_table[i][1] = i;
-				zinfo->color_table[i][2] = i;
-			}
-		}
-
-		regs = zinfo->regs;
-		/* Disable hardware cursor */
-		seq_w(regs, SEQ_CURSOR_Y_INDEX, 0x00);
-
-		retz3fb_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, fb_info);
-		retz3fb_setcolreg (254, 0, 0, 0, 0, fb_info);
-
-		strcpy(fb_info->modename, retz3fb_name);
-		fb_info->changevar = NULL;
-		fb_info->fbops = &retz3fb_ops;
-		fb_info->screen_base = zinfo->fbmem;
-		fb_info->disp = &zinfo->disp;
-		fb_info->currcon = -1;
-		fb_info->switch_con = &z3fb_switch;
-		fb_info->updatevar = &z3fb_updatevar;
-		fb_info->flags = FBINFO_FLAG_DEFAULT;
-		strlcpy(fb_info->fontname, fontname, sizeof(fb_info->fontname));
-
-		if (z3fb_mode == -1)
-			retz3fb_default = retz3fb_predefined[0].var;
-
-		retz3_decode_var(&retz3fb_default, &par);
-		retz3_encode_var(&retz3fb_default, &par);
-
-		do_fb_set_var(fb_info, &retz3fb_default, 0);
-		retz3fb_get_var(&zinfo->disp.var, -1, fb_info);
-
-		retz3fb_set_disp(-1, fb_info);
-
-		do_install_cmap(0, fb_info);
-
-		if (register_framebuffer(fb_info) < 0) {
-			iounmap(zinfo->base);
-			return -EINVAL;
-		}
-
-		printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of "
-		       "video memory\n", fb_info->node,
-		       fb_info->modename, zinfo->fbsize>>10);
-
-		/* FIXME: This driver cannot be unloaded yet */
-		res = 0;
-	}
-	return res;
-}
-
-
-static int z3fb_switch(int con, struct fb_info *info)
-{
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len)
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1,
-			    retz3_getcolreg, info);
-
-	do_fb_set_var(info, &fb_display[con].var, 1);
-	info->currcon = con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	return 0;
-}
-
-
-/*
- *    Update the `var' structure (called by fbcon.c)
- *
- *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
- *    Since it's called by a kernel driver, no range checking is done.
- */
-
-static int z3fb_updatevar(int con, struct fb_info *info)
-{
-	return 0;
-}
-
-/*
- *    Get a Video Mode
- */
-
-static int __init get_video_mode(const char *name)
-{
-	short i;
-
-	for (i = 0; i < NUM_TOTAL_MODES; i++)
-		if (!strcmp(name, retz3fb_predefined[i].name)){
-			retz3fb_default = retz3fb_predefined[i].var;
-			return i;
-		}
-	return -1;
-}
-
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return retz3fb_init();
-}
-#endif
-
-
-/*
- *  Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static void retz3_8_bmove(struct display *p, int sy, int sx,
-			  int dy, int dx, int height, int width)
-{
-	int fontwidth = fontwidth(p);
-
-	sx *= fontwidth;
-	dx *= fontwidth;
-	width *= fontwidth;
-
-	retz3_bitblt(p,
-		     (unsigned short)sx,
-		     (unsigned short)(sy*fontheight(p)),
-		     (unsigned short)dx,
-		     (unsigned short)(dy*fontheight(p)),
-		     (unsigned short)width,
-		     (unsigned short)(height*fontheight(p)),
-		     Z3BLTcopy,
-		     0xffff);
-}
-
-static void retz3_8_clear(struct vc_data *conp, struct display *p,
-			  int sy, int sx, int height, int width)
-{
-	unsigned short col;
-	int fontwidth = fontwidth(p);
-
-	sx *= fontwidth;
-	width *= fontwidth;
-
-	col = attr_bgcol_ec(p, conp);
-	col &= 0xff;
-	col |= (col << 8);
-
-	retz3_bitblt(p,
-		     (unsigned short)sx,
-		     (unsigned short)(sy*fontheight(p)),
-		     (unsigned short)sx,
-		     (unsigned short)(sy*fontheight(p)),
-		     (unsigned short)width,
-		     (unsigned short)(height*fontheight(p)),
-		     Z3BLTset,
-		     col);
-}
-
-
-static void retz3_putc(struct vc_data *conp, struct display *p, int c,
-		       int yy, int xx)
-{
-	retz3_busy(p);
-	fbcon_cfb8_putc(conp, p, c, yy, xx);
-}
-
-
-static void retz3_putcs(struct vc_data *conp, struct display *p,
-			const unsigned short *s, int count,
-			int yy, int xx)
-{
-	retz3_busy(p);
-	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
-}
-
-
-static void retz3_revc(struct display *p, int xx, int yy)
-{
-	retz3_busy(p);
-	fbcon_cfb8_revc(p, xx, yy);
-}
-
-
-static void retz3_clear_margins(struct vc_data* conp, struct display* p,
-				int bottom_only)
-{
-	retz3_busy(p);
-	fbcon_cfb8_clear_margins(conp, p, bottom_only);
-}
-
-
-static struct display_switch fbcon_retz3_8 = {
-	.setup		= fbcon_cfb8_setup,
-	.bmove		= retz3_8_bmove,
-	.clear		= retz3_8_clear,
-	.putc		= retz3_putc,
-	.putcs		= retz3_putcs,
-	.revc		= retz3_revc,
-	.clear_margins	= retz3_clear_margins,
-	.fontwidthmask	= FONTWIDTH(8)
-};
-#endif
diff --git a/drivers/video/retz3fb.h b/drivers/video/retz3fb.h
deleted file mode 100644
index 5cc7510..0000000
--- a/drivers/video/retz3fb.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * linux/drivers/video/retz3fb.h -- Defines and macros for the RetinaZ3 frame
- *				    buffer device
- *
- *    Copyright (C) 1997 Jes Sorensen
- *
- * History:
- *   - 22 Jan 97: Initial work
- *
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/*
- * Macros to read and write to registers.
- */
-#define reg_w(regs, reg,dat) (*(regs + reg) = dat)
-#define reg_r(regs, reg) (*(regs + reg))
-
-/*
- * Macro to access the sequencer.
- */
-#define seq_w(regs, sreg, sdat) \
-	do{ reg_w(regs, SEQ_IDX, sreg); reg_w(regs, SEQ_DATA, sdat); } while(0)
-
-/*
- * Macro to access the CRT controller.
- */
-#define crt_w(regs, creg, cdat) \
-	do{ reg_w(regs, CRT_IDX, creg); reg_w(regs, CRT_DATA, cdat); } while(0)
-
-/*
- * Macro to access the graphics controller.
- */
-#define gfx_w(regs, greg, gdat) \
-	do{ reg_w(regs, GFX_IDX, greg); reg_w(regs, GFX_DATA, gdat); } while(0)
-
-/*
- * Macro to access the attribute controller.
- */
-#define attr_w(regs, areg, adat) \
-	do{ reg_w(regs, ACT_IDX, areg); reg_w(regs, ACT_DATA, adat); } while(0)
-
-/*
- * Macro to access the pll.
- */
-#define pll_w(regs, preg, pdat) \
-	do{ reg_w(regs, PLL_IDX, preg); \
-	    reg_w(regs, PLL_DATA, (pdat & 0xff)); \
-	    reg_w(regs, PLL_DATA, (pdat >> 8));\
-	} while(0)
-
-/*
- * Offsets
- */
-#define VIDEO_MEM_OFFSET	0x00c00000
-#define ACM_OFFSET		0x00b00000
-
-/*
- * Accelerator Control Menu
- */
-#define ACM_PRIMARY_OFFSET	0x00
-#define ACM_SECONDARY_OFFSET	0x04
-#define ACM_MODE_CONTROL	0x08
-#define ACM_CURSOR_POSITION	0x0c
-#define ACM_START_STATUS	0x30
-#define ACM_CONTROL		0x34
-#define ACM_RASTEROP_ROTATION	0x38
-#define ACM_BITMAP_DIMENSION	0x3c
-#define ACM_DESTINATION		0x40
-#define ACM_SOURCE		0x44
-#define ACM_PATTERN		0x48
-#define ACM_FOREGROUND		0x4c
-#define ACM_BACKGROUND		0x50
-
-/*
- * Video DAC addresses
- */
-#define VDAC_ADDRESS		0x03c8
-#define VDAC_ADDRESS_W		0x03c8
-#define VDAC_ADDRESS_R		0x03c7
-#define VDAC_STATE		0x03c7
-#define VDAC_DATA		0x03c9
-#define VDAC_MASK		0x03c6
-
-/*
- * Sequencer
- */
-#define SEQ_IDX			0x03c4	/* Sequencer Index */
-#define SEQ_DATA		0x03c5
-#define SEQ_RESET		0x00
-#define SEQ_CLOCKING_MODE	0x01
-#define SEQ_MAP_MASK		0x02
-#define SEQ_CHAR_MAP_SELECT	0x03
-#define SEQ_MEMORY_MODE		0x04
-#define SEQ_EXTENDED_ENABLE	0x05	/* NCR extensions */
-#define SEQ_UNKNOWN1         	0x06
-#define SEQ_UNKNOWN2         	0x07
-#define SEQ_CHIP_ID		0x08
-#define SEQ_UNKNOWN3         	0x09
-#define SEQ_CURSOR_COLOR1	0x0a
-#define SEQ_CURSOR_COLOR0	0x0b
-#define SEQ_CURSOR_CONTROL	0x0c
-#define SEQ_CURSOR_X_LOC_HI	0x0d
-#define SEQ_CURSOR_X_LOC_LO	0x0e
-#define SEQ_CURSOR_Y_LOC_HI	0x0f
-#define SEQ_CURSOR_Y_LOC_LO	0x10
-#define SEQ_CURSOR_X_INDEX	0x11
-#define SEQ_CURSOR_Y_INDEX	0x12
-#define SEQ_CURSOR_STORE_HI	0x13
-#define SEQ_CURSOR_STORE_LO	0x14
-#define SEQ_CURSOR_ST_OFF_HI	0x15
-#define SEQ_CURSOR_ST_OFF_LO	0x16
-#define SEQ_CURSOR_PIXELMASK	0x17
-#define SEQ_PRIM_HOST_OFF_HI	0x18
-#define SEQ_PRIM_HOST_OFF_LO	0x19
-#define SEQ_LINEAR_0		0x1a
-#define SEQ_LINEAR_1		0x1b
-#define SEQ_SEC_HOST_OFF_HI	0x1c
-#define SEQ_SEC_HOST_OFF_LO	0x1d
-#define SEQ_EXTENDED_MEM_ENA	0x1e
-#define SEQ_EXT_CLOCK_MODE	0x1f
-#define SEQ_EXT_VIDEO_ADDR	0x20
-#define SEQ_EXT_PIXEL_CNTL	0x21
-#define SEQ_BUS_WIDTH_FEEDB	0x22
-#define SEQ_PERF_SELECT		0x23
-#define SEQ_COLOR_EXP_WFG	0x24
-#define SEQ_COLOR_EXP_WBG	0x25
-#define SEQ_EXT_RW_CONTROL	0x26
-#define SEQ_MISC_FEATURE_SEL	0x27
-#define SEQ_COLOR_KEY_CNTL	0x28
-#define SEQ_COLOR_KEY_MATCH0	0x29
-#define SEQ_COLOR_KEY_MATCH1 	0x2a
-#define SEQ_COLOR_KEY_MATCH2 	0x2b
-#define SEQ_UNKNOWN6         	0x2c
-#define SEQ_CRC_CONTROL		0x2d
-#define SEQ_CRC_DATA_LOW	0x2e
-#define SEQ_CRC_DATA_HIGH	0x2f
-#define SEQ_MEMORY_MAP_CNTL	0x30
-#define SEQ_ACM_APERTURE_1	0x31
-#define SEQ_ACM_APERTURE_2	0x32
-#define SEQ_ACM_APERTURE_3	0x33
-#define SEQ_BIOS_UTILITY_0	0x3e
-#define SEQ_BIOS_UTILITY_1	0x3f
-
-/*
- * Graphics Controller
- */
-#define GFX_IDX			0x03ce
-#define GFX_DATA		0x03cf
-#define GFX_SET_RESET		0x00
-#define GFX_ENABLE_SET_RESET	0x01
-#define GFX_COLOR_COMPARE	0x02
-#define GFX_DATA_ROTATE		0x03
-#define GFX_READ_MAP_SELECT	0x04
-#define GFX_GRAPHICS_MODE	0x05
-#define GFX_MISC		0x06
-#define GFX_COLOR_XCARE		0x07
-#define GFX_BITMASK		0x08
-
-/*
- * CRT Controller
- */
-#define CRT_IDX			0x03d4
-#define CRT_DATA		0x03d5
-#define CRT_HOR_TOTAL		0x00
-#define CRT_HOR_DISP_ENA_END	0x01
-#define CRT_START_HOR_BLANK	0x02
-#define CRT_END_HOR_BLANK	0x03
-#define CRT_START_HOR_RETR	0x04
-#define CRT_END_HOR_RETR	0x05
-#define CRT_VER_TOTAL		0x06
-#define CRT_OVERFLOW		0x07
-#define CRT_PRESET_ROW_SCAN	0x08
-#define CRT_MAX_SCAN_LINE	0x09
-#define CRT_CURSOR_START	0x0a
-#define CRT_CURSOR_END		0x0b
-#define CRT_START_ADDR_HIGH	0x0c
-#define CRT_START_ADDR_LOW	0x0d
-#define CRT_CURSOR_LOC_HIGH	0x0e
-#define CRT_CURSOR_LOC_LOW	0x0f
-#define CRT_START_VER_RETR	0x10
-#define CRT_END_VER_RETR	0x11
-#define CRT_VER_DISP_ENA_END	0x12
-#define CRT_OFFSET		0x13
-#define CRT_UNDERLINE_LOC	0x14
-#define CRT_START_VER_BLANK	0x15
-#define CRT_END_VER_BLANK	0x16
-#define CRT_MODE_CONTROL	0x17
-#define CRT_LINE_COMPARE	0x18
-#define CRT_UNKNOWN1         	0x19
-#define CRT_UNKNOWN2         	0x1a
-#define CRT_UNKNOWN3         	0x1b
-#define CRT_UNKNOWN4         	0x1c
-#define CRT_UNKNOWN5         	0x1d
-#define CRT_UNKNOWN6         	0x1e
-#define CRT_UNKNOWN7         	0x1f
-#define CRT_UNKNOWN8         	0x20
-#define CRT_UNKNOWN9		0x21
-#define CRT_UNKNOWN10		0x22
-#define CRT_UNKNOWN11      	0x23
-#define CRT_UNKNOWN12      	0x24
-#define CRT_UNKNOWN13      	0x25
-#define CRT_UNKNOWN14      	0x26
-#define CRT_UNKNOWN15      	0x27
-#define CRT_UNKNOWN16      	0x28
-#define CRT_UNKNOWN17      	0x29
-#define CRT_UNKNOWN18      	0x2a
-#define CRT_UNKNOWN19      	0x2b
-#define CRT_UNKNOWN20      	0x2c
-#define CRT_UNKNOWN21      	0x2d
-#define CRT_UNKNOWN22      	0x2e
-#define CRT_UNKNOWN23      	0x2f
-#define CRT_EXT_HOR_TIMING1	0x30	/* NCR crt extensions */
-#define CRT_EXT_START_ADDR	0x31
-#define CRT_EXT_HOR_TIMING2	0x32
-#define CRT_EXT_VER_TIMING	0x33
-#define CRT_MONITOR_POWER	0x34
-
-/*
- * General Registers
- */
-#define GREG_STATUS0_R		0x03c2
-#define GREG_STATUS1_R		0x03da
-#define GREG_MISC_OUTPUT_R	0x03cc
-#define GREG_MISC_OUTPUT_W	0x03c2	
-#define GREG_FEATURE_CONTROL_R	0x03ca
-#define GREG_FEATURE_CONTROL_W	0x03da
-#define GREG_POS		0x0102
-
-/*
- * Attribute Controller
- */
-#define ACT_IDX			0x03C0
-#define ACT_ADDRESS_R		0x03C0
-#define ACT_DATA		0x03C0
-#define ACT_ADDRESS_RESET	0x03DA
-#define ACT_PALETTE0		0x00
-#define ACT_PALETTE1		0x01
-#define ACT_PALETTE2		0x02
-#define ACT_PALETTE3		0x03
-#define ACT_PALETTE4		0x04
-#define ACT_PALETTE5		0x05
-#define ACT_PALETTE6		0x06
-#define ACT_PALETTE7		0x07
-#define ACT_PALETTE8		0x08
-#define ACT_PALETTE9		0x09
-#define ACT_PALETTE10		0x0A
-#define ACT_PALETTE11		0x0B
-#define ACT_PALETTE12		0x0C
-#define ACT_PALETTE13		0x0D
-#define ACT_PALETTE14		0x0E
-#define ACT_PALETTE15		0x0F
-#define ACT_ATTR_MODE_CNTL	0x10
-#define ACT_OVERSCAN_COLOR	0x11
-#define ACT_COLOR_PLANE_ENA	0x12
-#define ACT_HOR_PEL_PANNING	0x13
-#define ACT_COLOR_SELECT	0x14
-
-/*
- * PLL
- */
-#define PLL_IDX			0x83c8
-#define PLL_DATA		0x83c9
-
-/*
- * Blitter operations
- */
-#define	Z3BLTclear		0x00	/* 0 */
-#define Z3BLTand		0x80	/* src AND dst */
-#define Z3BLTandReverse		0x40	/* src AND NOT dst */
-#define Z3BLTcopy		0xc0	/* src */
-#define Z3BLTandInverted	0x20	/* NOT src AND dst */
-#define	Z3BLTnoop		0xa0	/* dst */
-#define Z3BLTxor		0x60	/* src XOR dst */
-#define Z3BLTor			0xe0	/* src OR dst */
-#define Z3BLTnor		0x10	/* NOT src AND NOT dst */
-#define Z3BLTequiv		0x90	/* NOT src XOR dst */
-#define Z3BLTinvert		0x50	/* NOT dst */
-#define Z3BLTorReverse		0xd0	/* src OR NOT dst */
-#define Z3BLTcopyInverted	0x30	/* NOT src */
-#define Z3BLTorInverted		0xb0	/* NOT src OR dst */
-#define Z3BLTnand		0x70	/* NOT src OR NOT dst */
-#define Z3BLTset		0xf0	/* 1 */
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 1a13966..f2e9b74 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -894,7 +894,8 @@
 	return rc;
 }
 
-static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+static void riva_update_var(struct fb_var_screeninfo *var,
+			    const struct fb_videomode *modedb)
 {
 	NVTRACE_ENTER();
 	var->xres = var->xres_virtual = modedb->xres;
@@ -1101,10 +1102,10 @@
 static int rivafb_open(struct fb_info *info, int user)
 {
 	struct riva_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
 	NVTRACE_ENTER();
-	if (!cnt) {
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
 #ifdef CONFIG_X86
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_MODE  | VGA_SAVE_FONTS;
@@ -1119,7 +1120,8 @@
 	
 		riva_save_state(par, &par->initial_state);
 	}
-	atomic_inc(&par->ref_count);
+	par->ref_count++;
+	mutex_unlock(&par->open_lock);
 	NVTRACE_LEAVE();
 	return 0;
 }
@@ -1127,12 +1129,14 @@
 static int rivafb_release(struct fb_info *info, int user)
 {
 	struct riva_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
 	NVTRACE_ENTER();
-	if (!cnt)
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
+		mutex_unlock(&par->open_lock);
 		return -EINVAL;
-	if (cnt == 1) {
+	}
+	if (par->ref_count == 1) {
 		par->riva.LockUnlock(&par->riva, 0);
 		par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
 		riva_load_state(par, &par->initial_state);
@@ -1141,14 +1145,15 @@
 #endif
 		par->riva.LockUnlock(&par->riva, 1);
 	}
-	atomic_dec(&par->ref_count);
+	par->ref_count--;
+	mutex_unlock(&par->open_lock);
 	NVTRACE_LEAVE();
 	return 0;
 }
 
 static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct fb_videomode *mode;
+	const struct fb_videomode *mode;
 	struct riva_par *par = info->par;
 	int nom, den;		/* translating from pixels->bytes */
 	int mode_valid = 0;
@@ -1980,12 +1985,11 @@
 	default_par = info->par;
 	default_par->pdev = pd;
 
-	info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
+	info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL);
 	if (info->pixmap.addr == NULL) {
 	    	ret = -ENOMEM;
 		goto err_framebuffer_release;
 	}
-	memset(info->pixmap.addr, 0, 8 * 1024);
 
 	ret = pci_enable_device(pd);
 	if (ret < 0) {
@@ -1999,6 +2003,7 @@
 		goto err_disable_device;
 	}
 
+	mutex_init(&default_par->open_lock);
 	default_par->riva.Architecture = riva_get_arch(pd);
 
 	default_par->Chipset = (pd->vendor << 16) | pd->device;
diff --git a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h
index 7fa13fc..48ead6d 100644
--- a/drivers/video/riva/rivafb.h
+++ b/drivers/video/riva/rivafb.h
@@ -53,7 +53,8 @@
 #ifdef CONFIG_X86
 	struct vgastate state;
 #endif
-	atomic_t ref_count;
+	struct mutex open_lock;
+	unsigned int ref_count;
 	unsigned char *EDID;
 	unsigned int Chipset;
 	int forceCRTC;
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
new file mode 100644
index 0000000..3162c37
--- /dev/null
+++ b/drivers/video/s3fb.c
@@ -0,0 +1,1180 @@
+/*
+ * linux/drivers/video/s3fb.c -- Frame buffer device driver for S3 Trio/Virge
+ *
+ * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Code is based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
+ * which is based on the code of neofb.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */
+#include <video/vga.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+struct s3fb_info {
+	int chip, rev, mclk_freq;
+	int mtrr_reg;
+	struct vgastate state;
+	struct mutex open_lock;
+	unsigned int ref_count;
+	u32 pseudo_palette[16];
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+static const struct svga_fb_format s3fb_formats[] = {
+	{ 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,	FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
+		FB_TYPE_INTERLEAVED_PLANES, 1,		FB_VISUAL_PSEUDOCOLOR, 8, 16},
+	{ 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_PSEUDOCOLOR, 4, 8},
+	{16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
+	{16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 2, 4},
+	{24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
+	{32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
+		FB_TYPE_PACKED_PIXELS, 0,		FB_VISUAL_TRUECOLOR, 1, 2},
+	SVGA_FORMAT_END
+};
+
+
+static const struct svga_pll s3_pll = {3, 129, 3, 33, 0, 3,
+	60000, 240000, 14318};
+
+static const int s3_memsizes[] = {4096, 0, 3072, 8192, 2048, 6144, 1024, 512};
+
+static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", "S3 Trio64V+",
+			"S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
+			"S3 Plato/PX", "S3 Aurora64VP", "S3 Virge",
+			"S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
+			"S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P"};
+
+#define CHIP_UNKNOWN		0x00
+#define CHIP_732_TRIO32		0x01
+#define CHIP_764_TRIO64		0x02
+#define CHIP_765_TRIO64VP	0x03
+#define CHIP_767_TRIO64UVP	0x04
+#define CHIP_775_TRIO64V2_DX	0x05
+#define CHIP_785_TRIO64V2_GX	0x06
+#define CHIP_551_PLATO_PX	0x07
+#define CHIP_M65_AURORA64VP	0x08
+#define CHIP_325_VIRGE		0x09
+#define CHIP_988_VIRGE_VX	0x0A
+#define CHIP_375_VIRGE_DX	0x0B
+#define CHIP_385_VIRGE_GX	0x0C
+#define CHIP_356_VIRGE_GX2	0x0D
+#define CHIP_357_VIRGE_GX2P	0x0E
+#define CHIP_359_VIRGE_GX2P	0x0F
+
+#define CHIP_XXX_TRIO		0x80
+#define CHIP_XXX_TRIO64V2_DXGX	0x81
+#define CHIP_XXX_VIRGE_DXGX	0x82
+
+#define CHIP_UNDECIDED_FLAG	0x80
+#define CHIP_MASK		0xFF
+
+/* CRT timing register sets */
+
+static const struct vga_regset s3_h_total_regs[]        = {{0x00, 0, 7}, {0x5D, 0, 0}, VGA_REGSET_END};
+static const struct vga_regset s3_h_display_regs[]      = {{0x01, 0, 7}, {0x5D, 1, 1}, VGA_REGSET_END};
+static const struct vga_regset s3_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x5D, 2, 2}, VGA_REGSET_END};
+static const struct vga_regset s3_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7}, VGA_REGSET_END};
+static const struct vga_regset s3_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x5D, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset s3_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
+
+static const struct vga_regset s3_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x5E, 0, 0}, VGA_REGSET_END};
+static const struct vga_regset s3_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x5E, 1, 1}, VGA_REGSET_END};
+static const struct vga_regset s3_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x5E, 2, 2}, VGA_REGSET_END};
+static const struct vga_regset s3_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
+static const struct vga_regset s3_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x5E, 4, 4}, VGA_REGSET_END};
+static const struct vga_regset s3_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
+
+static const struct vga_regset s3_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, {0x5E, 6, 6}, VGA_REGSET_END};
+static const struct vga_regset s3_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x31, 4, 5}, {0x51, 0, 1}, VGA_REGSET_END};
+static const struct vga_regset s3_offset_regs[]         = {{0x13, 0, 7}, {0x51, 4, 5}, VGA_REGSET_END}; /* set 0x43 bit 2 to 0 */
+
+static const struct svga_timing_regs s3_timing_regs     = {
+	s3_h_total_regs, s3_h_display_regs, s3_h_blank_start_regs,
+	s3_h_blank_end_regs, s3_h_sync_start_regs, s3_h_sync_end_regs,
+	s3_v_total_regs, s3_v_display_regs, s3_v_blank_start_regs,
+	s3_v_blank_end_regs, s3_v_sync_start_regs, s3_v_sync_end_regs,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+/* Module parameters */
+
+
+static char *mode = "640x480-8@60";
+
+#ifdef CONFIG_MTRR
+static int mtrr = 1;
+#endif
+
+static int fasttext = 1;
+
+
+MODULE_AUTHOR("(c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("fbdev driver for S3 Trio/Virge");
+
+module_param(mode, charp, 0444);
+MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc)");
+
+#ifdef CONFIG_MTRR
+module_param(mtrr, int, 0444);
+MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
+#endif
+
+module_param(fasttext, int, 0644);
+MODULE_PARM_DESC(fasttext, "Enable S3 fast text mode (1=enable, 0=disable, default=1)");
+
+
+/* ------------------------------------------------------------------------- */
+
+/* Set font in S3 fast text mode */
+
+static void s3fb_settile_fast(struct fb_info *info, struct fb_tilemap *map)
+{
+	const u8 *font = map->data;
+	u8* fb = (u8 *) info->screen_base;
+	int i, c;
+
+	if ((map->width != 8) || (map->height != 16) ||
+	    (map->depth != 1) || (map->length != 256)) {
+	    	printk(KERN_ERR "fb%d: unsupported font parameters: width %d, height %d, depth %d, length %d\n",
+			info->node, map->width, map->height, map->depth, map->length);
+		return;
+	}
+
+	fb += 2;
+	for (i = 0; i < map->height; i++) {
+		for (c = 0; c < map->length; c++) {
+			fb[c * 4] = font[c * map->height + i];
+		}
+		fb += 1024;
+	}
+}
+
+
+
+static struct fb_tile_ops s3fb_tile_ops = {
+	.fb_settile	= svga_settile,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = svga_tilecursor,
+};
+
+static struct fb_tile_ops s3fb_fast_tile_ops = {
+	.fb_settile	= s3fb_settile_fast,
+	.fb_tilecopy	= svga_tilecopy,
+	.fb_tilefill    = svga_tilefill,
+	.fb_tileblit    = svga_tileblit,
+	.fb_tilecursor  = svga_tilecursor,
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+/* image data is MSB-first, fb structure is MSB-first too */
+static inline u32 expand_color(u32 c)
+{
+	return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
+}
+
+/* s3fb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void s3fb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = expand_color(image->fg_color);
+	u32 bg = expand_color(image->bg_color);
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = *(src++) * 0x01010101;
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+
+}
+
+/* s3fb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
+static void s3fb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	u32 fg = expand_color(rect->color);
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	int x, y;
+
+	dst1 = info->screen_base + (rect->dy * info->fix.line_length)
+		 + ((rect->dx / 8) * 4);
+
+	for (y = 0; y < rect->height; y++) {
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < rect->width; x += 8) {
+			fb_writel(fg, dst++);
+		}
+		dst1 += info->fix.line_length;
+	}
+}
+
+
+/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
+static inline u32 expand_pixel(u32 c)
+{
+	return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
+		((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
+}
+
+/* s3fb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
+static void s3fb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	u32 fg = image->fg_color * 0x11111111;
+	u32 bg = image->bg_color * 0x11111111;
+	const u8 *src1, *src;
+	u8 __iomem *dst1;
+	u32 __iomem *dst;
+	u32 val;
+	int x, y;
+
+	src1 = image->data;
+	dst1 = info->screen_base + (image->dy * info->fix.line_length)
+		 + ((image->dx / 8) * 4);
+
+	for (y = 0; y < image->height; y++) {
+		src = src1;
+		dst = (u32 __iomem *) dst1;
+		for (x = 0; x < image->width; x += 8) {
+			val = expand_pixel(*(src++));
+			val = (val & fg) | (~val & bg);
+			fb_writel(val, dst++);
+		}
+		src1 += image->width / 8;
+		dst1 += info->fix.line_length;
+	}
+}
+
+static void s3fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
+	    && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
+		if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
+			s3fb_iplan_imageblit(info, image);
+		else
+			s3fb_cfb4_imageblit(info, image);
+	} else
+		cfb_imageblit(info, image);
+}
+
+static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	if ((info->var.bits_per_pixel == 4)
+	    && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
+	    && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
+		s3fb_iplan_fillrect(info, rect);
+	 else
+		cfb_fillrect(info, rect);
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+
+
+static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
+{
+	u16 m, n, r;
+	u8 regval;
+
+	svga_compute_pll(&s3_pll, 1000000000 / pixclock, &m, &n, &r, info->node);
+
+	/* Set VGA misc register  */
+	regval = vga_r(NULL, VGA_MIS_R);
+	vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
+
+	/* Set S3 clock registers */
+	vga_wseq(NULL, 0x12, ((n - 2) | (r << 5)));
+	vga_wseq(NULL, 0x13, m - 2);
+
+	udelay(1000);
+
+	/* Activate clock - write 0, 1, 0 to seq/15 bit 5 */
+	regval = vga_rseq (NULL, 0x15); /* | 0x80; */
+	vga_wseq(NULL, 0x15, regval & ~(1<<5));
+	vga_wseq(NULL, 0x15, regval |  (1<<5));
+	vga_wseq(NULL, 0x15, regval & ~(1<<5));
+}
+
+
+/* Open framebuffer */
+
+static int s3fb_open(struct fb_info *info, int user)
+{
+	struct s3fb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		memset(&(par->state), 0, sizeof(struct vgastate));
+		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
+		par->state.num_crtc = 0x70;
+		par->state.num_seq = 0x20;
+		save_vga(&(par->state));
+	}
+
+	par->ref_count++;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+/* Close framebuffer */
+
+static int s3fb_release(struct fb_info *info, int user)
+{
+	struct s3fb_info *par = info->par;
+
+	mutex_lock(&(par->open_lock));
+	if (par->ref_count == 0) {
+		mutex_unlock(&(par->open_lock));
+		return -EINVAL;
+	}
+
+	if (par->ref_count == 1)
+		restore_vga(&(par->state));
+
+	par->ref_count--;
+	mutex_unlock(&(par->open_lock));
+
+	return 0;
+}
+
+/* Validate passed in var */
+
+static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct s3fb_info *par = info->par;
+	int rv, mem, step;
+
+	/* Find appropriate format */
+	rv = svga_match_format (s3fb_formats, var, NULL);
+	if ((rv < 0) || ((par->chip == CHIP_988_VIRGE_VX) ? (rv == 7) : (rv == 6)))
+	{		/* 24bpp on VIRGE VX, 32bpp on others */
+		printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node);
+		return rv;
+	}
+
+	/* Do not allow to have real resoulution larger than virtual */
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	/* Round up xres_virtual to have proper alignment of lines */
+	step = s3fb_formats[rv].xresstep - 1;
+	var->xres_virtual = (var->xres_virtual+step) & ~step;
+
+	/* Check whether have enough memory */
+	mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
+	if (mem > info->screen_size)
+	{
+		printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n",
+			info->node, mem >> 10, (unsigned int) (info->screen_size >> 10));
+		return -EINVAL;
+	}
+
+	rv = svga_check_timings (&s3_timing_regs, var, info->node);
+	if (rv < 0)
+	{
+		printk(KERN_ERR "fb%d: invalid timings requested\n", info->node);
+		return rv;
+	}
+
+	return 0;
+}
+
+/* Set video mode from par */
+
+static int s3fb_set_par(struct fb_info *info)
+{
+	struct s3fb_info *par = info->par;
+	u32 value, mode, hmul, offset_value, screen_size, multiplex;
+	u32 bpp = info->var.bits_per_pixel;
+
+	if (bpp != 0) {
+		info->fix.ypanstep = 1;
+		info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
+
+		info->flags &= ~FBINFO_MISC_TILEBLITTING;
+		info->tileops = NULL;
+
+		offset_value = (info->var.xres_virtual * bpp) / 64;
+		screen_size = info->var.yres_virtual * info->fix.line_length;
+	} else {
+		info->fix.ypanstep = 16;
+		info->fix.line_length = 0;
+
+		info->flags |= FBINFO_MISC_TILEBLITTING;
+		info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops;
+
+		offset_value = info->var.xres_virtual / 16;
+		screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
+	}
+
+	info->var.xoffset = 0;
+	info->var.yoffset = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+
+	/* Unlock registers */
+	vga_wcrt(NULL, 0x38, 0x48);
+	vga_wcrt(NULL, 0x39, 0xA5);
+	vga_wseq(NULL, 0x08, 0x06);
+	svga_wcrt_mask(0x11, 0x00, 0x80);
+
+	/* Blank screen and turn off sync */
+	svga_wseq_mask(0x01, 0x20, 0x20);
+	svga_wcrt_mask(0x17, 0x00, 0x80);
+
+	/* Set default values */
+	svga_set_default_gfx_regs();
+	svga_set_default_atc_regs();
+	svga_set_default_seq_regs();
+	svga_set_default_crt_regs();
+	svga_wcrt_multi(s3_line_compare_regs, 0xFFFFFFFF);
+	svga_wcrt_multi(s3_start_address_regs, 0);
+
+	/* S3 specific initialization */
+	svga_wcrt_mask(0x58, 0x10, 0x10); /* enable linear framebuffer */
+	svga_wcrt_mask(0x31, 0x08, 0x08); /* enable sequencer access to framebuffer above 256 kB */
+
+/*	svga_wcrt_mask(0x33, 0x08, 0x08); */ /* DDR ?	*/
+/*	svga_wcrt_mask(0x43, 0x01, 0x01); */ /* DDR ?	*/
+	svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ?	*/
+	svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ?	*/
+
+	svga_wcrt_mask(0x5D, 0x00, 0x28); // Clear strange HSlen bits
+
+/*	svga_wcrt_mask(0x58, 0x03, 0x03); */
+
+/*	svga_wcrt_mask(0x53, 0x12, 0x13); */ /* enable MMIO */
+/*	svga_wcrt_mask(0x40, 0x08, 0x08); */ /* enable write buffer */
+
+
+	/* Set the offset register */
+	pr_debug("fb%d: offset register       : %d\n", info->node, offset_value);
+	svga_wcrt_multi(s3_offset_regs, offset_value);
+
+	vga_wcrt(NULL, 0x54, 0x18); /* M parameter */
+	vga_wcrt(NULL, 0x60, 0xff); /* N parameter */
+	vga_wcrt(NULL, 0x61, 0xff); /* L parameter */
+	vga_wcrt(NULL, 0x62, 0xff); /* L parameter */
+
+	vga_wcrt(NULL, 0x3A, 0x35);
+	svga_wattr(0x33, 0x00);
+
+	if (info->var.vmode & FB_VMODE_DOUBLE)
+		svga_wcrt_mask(0x09, 0x80, 0x80);
+	else
+		svga_wcrt_mask(0x09, 0x00, 0x80);
+
+	if (info->var.vmode & FB_VMODE_INTERLACED)
+		svga_wcrt_mask(0x42, 0x20, 0x20);
+	else
+		svga_wcrt_mask(0x42, 0x00, 0x20);
+
+	/* Disable hardware graphics cursor */
+	svga_wcrt_mask(0x45, 0x00, 0x01);
+	/* Disable Streams engine */
+	svga_wcrt_mask(0x67, 0x00, 0x0C);
+
+	mode = svga_match_format(s3fb_formats, &(info->var), &(info->fix));
+
+	/* S3 virge DX hack */
+	if (par->chip == CHIP_375_VIRGE_DX) {
+		vga_wcrt(NULL, 0x86, 0x80);
+		vga_wcrt(NULL, 0x90, 0x00);
+	}
+
+	/* S3 virge VX hack */
+	if (par->chip == CHIP_988_VIRGE_VX) {
+		vga_wcrt(NULL, 0x50, 0x00);
+		vga_wcrt(NULL, 0x67, 0x50);
+
+		vga_wcrt(NULL, 0x63, (mode <= 2) ? 0x90 : 0x09);
+		vga_wcrt(NULL, 0x66, 0x90);
+	}
+
+	svga_wcrt_mask(0x31, 0x00, 0x40);
+	multiplex = 0;
+	hmul = 1;
+
+	/* Set mode-specific register values */
+	switch (mode) {
+	case 0:
+		pr_debug("fb%d: text mode\n", info->node);
+		svga_set_textmode_vga_regs();
+
+		/* Set additional registers like in 8-bit mode */
+		svga_wcrt_mask(0x50, 0x00, 0x30);
+		svga_wcrt_mask(0x67, 0x00, 0xF0);
+
+		/* Disable enhanced mode */
+		svga_wcrt_mask(0x3A, 0x00, 0x30);
+
+		if (fasttext) {
+			pr_debug("fb%d: high speed text mode set\n", info->node);
+			svga_wcrt_mask(0x31, 0x40, 0x40);
+		}
+		break;
+	case 1:
+		pr_debug("fb%d: 4 bit pseudocolor\n", info->node);
+		vga_wgfx(NULL, VGA_GFX_MODE, 0x40);
+
+		/* Set additional registers like in 8-bit mode */
+		svga_wcrt_mask(0x50, 0x00, 0x30);
+		svga_wcrt_mask(0x67, 0x00, 0xF0);
+
+		/* disable enhanced mode */
+		svga_wcrt_mask(0x3A, 0x00, 0x30);
+		break;
+	case 2:
+		pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);
+
+		/* Set additional registers like in 8-bit mode */
+		svga_wcrt_mask(0x50, 0x00, 0x30);
+		svga_wcrt_mask(0x67, 0x00, 0xF0);
+
+		/* disable enhanced mode */
+		svga_wcrt_mask(0x3A, 0x00, 0x30);
+		break;
+	case 3:
+		pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
+		if (info->var.pixclock > 20000) {
+			svga_wcrt_mask(0x50, 0x00, 0x30);
+			svga_wcrt_mask(0x67, 0x00, 0xF0);
+		} else {
+			svga_wcrt_mask(0x50, 0x00, 0x30);
+			svga_wcrt_mask(0x67, 0x10, 0xF0);
+			multiplex = 1;
+		}
+		break;
+	case 4:
+		pr_debug("fb%d: 5/5/5 truecolor\n", info->node);
+		if (par->chip == CHIP_988_VIRGE_VX) {
+			if (info->var.pixclock > 20000)
+				svga_wcrt_mask(0x67, 0x20, 0xF0);
+			else
+				svga_wcrt_mask(0x67, 0x30, 0xF0);
+		} else {
+			svga_wcrt_mask(0x50, 0x10, 0x30);
+			svga_wcrt_mask(0x67, 0x30, 0xF0);
+			hmul = 2;
+		}
+		break;
+	case 5:
+		pr_debug("fb%d: 5/6/5 truecolor\n", info->node);
+		if (par->chip == CHIP_988_VIRGE_VX) {
+			if (info->var.pixclock > 20000)
+				svga_wcrt_mask(0x67, 0x40, 0xF0);
+			else
+				svga_wcrt_mask(0x67, 0x50, 0xF0);
+		} else {
+			svga_wcrt_mask(0x50, 0x10, 0x30);
+			svga_wcrt_mask(0x67, 0x50, 0xF0);
+			hmul = 2;
+		}
+		break;
+	case 6:
+		/* VIRGE VX case */
+		pr_debug("fb%d: 8/8/8 truecolor\n", info->node);
+		svga_wcrt_mask(0x67, 0xD0, 0xF0);
+		break;
+	case 7:
+		pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node);
+		svga_wcrt_mask(0x50, 0x30, 0x30);
+		svga_wcrt_mask(0x67, 0xD0, 0xF0);
+		break;
+	default:
+		printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node);
+		return -EINVAL;
+	}
+
+	if (par->chip != CHIP_988_VIRGE_VX) {
+		svga_wseq_mask(0x15, multiplex ? 0x10 : 0x00, 0x10);
+		svga_wseq_mask(0x18, multiplex ? 0x80 : 0x00, 0x80);
+	}
+
+	s3_set_pixclock(info, info->var.pixclock);
+	svga_set_timings(&s3_timing_regs, &(info->var), hmul, 1,
+			 (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
+			 (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
+			 hmul, info->node);
+
+	/* Set interlaced mode start/end register */
+	value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
+	value = ((value * hmul) / 8) - 5;
+	vga_wcrt(NULL, 0x3C, (value + 1) / 2);
+
+	memset((u8*)info->screen_base, 0x00, screen_size);
+	/* Device and screen back on */
+	svga_wcrt_mask(0x17, 0x80, 0x80);
+	svga_wseq_mask(0x01, 0x00, 0x20);
+
+	return 0;
+}
+
+/* Set a colour register */
+
+static int s3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+				u_int transp, struct fb_info *fb)
+{
+	switch (fb->var.bits_per_pixel) {
+	case 0:
+	case 4:
+		if (regno >= 16)
+			return -EINVAL;
+
+		if ((fb->var.bits_per_pixel == 4) &&
+		    (fb->var.nonstd == 0)) {
+			outb(0xF0, VGA_PEL_MSK);
+			outb(regno*16, VGA_PEL_IW);
+		} else {
+			outb(0x0F, VGA_PEL_MSK);
+			outb(regno, VGA_PEL_IW);
+		}
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 8:
+		if (regno >= 256)
+			return -EINVAL;
+
+		outb(0xFF, VGA_PEL_MSK);
+		outb(regno, VGA_PEL_IW);
+		outb(red >> 10, VGA_PEL_D);
+		outb(green >> 10, VGA_PEL_D);
+		outb(blue >> 10, VGA_PEL_D);
+		break;
+	case 16:
+		if (regno >= 16)
+			return -EINVAL;
+
+		if (fb->var.green.length == 5)
+			((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
+				((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
+		else if (fb->var.green.length == 6)
+			((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
+				((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+		else return -EINVAL;
+		break;
+	case 24:
+	case 32:
+		if (regno >= 16)
+			return -EINVAL;
+
+		((u32*)fb->pseudo_palette)[regno] = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) |
+			(green & 0xFF00) | ((blue & 0xFF00) >> 8);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/* Set the display blanking state */
+
+static int s3fb_blank(int blank_mode, struct fb_info *info)
+{
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		pr_debug("fb%d: unblank\n", info->node);
+		svga_wcrt_mask(0x56, 0x00, 0x06);
+		svga_wseq_mask(0x01, 0x00, 0x20);
+		break;
+	case FB_BLANK_NORMAL:
+		pr_debug("fb%d: blank\n", info->node);
+		svga_wcrt_mask(0x56, 0x00, 0x06);
+		svga_wseq_mask(0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		pr_debug("fb%d: hsync\n", info->node);
+		svga_wcrt_mask(0x56, 0x02, 0x06);
+		svga_wseq_mask(0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		pr_debug("fb%d: vsync\n", info->node);
+		svga_wcrt_mask(0x56, 0x04, 0x06);
+		svga_wseq_mask(0x01, 0x20, 0x20);
+		break;
+	case FB_BLANK_POWERDOWN:
+		pr_debug("fb%d: sync down\n", info->node);
+		svga_wcrt_mask(0x56, 0x06, 0x06);
+		svga_wseq_mask(0x01, 0x20, 0x20);
+		break;
+	}
+
+	return 0;
+}
+
+
+/* Pan the display */
+
+static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) {
+
+	unsigned int offset;
+
+	/* Validate the offsets */
+	if ((var->xoffset + var->xres) > var->xres_virtual)
+		return -EINVAL;
+	if ((var->yoffset + var->yres) > var->yres_virtual)
+		return -EINVAL;
+
+	/* Calculate the offset */
+	if (var->bits_per_pixel == 0) {
+		offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
+		offset = offset >> 2;
+	} else {
+		offset = (var->yoffset * info->fix.line_length) +
+			 (var->xoffset * var->bits_per_pixel / 8);
+		offset = offset >> 2;
+	}
+
+	/* Set the offset */
+	svga_wcrt_multi(s3_start_address_regs, offset);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Frame buffer operations */
+
+static struct fb_ops s3fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= s3fb_open,
+	.fb_release	= s3fb_release,
+	.fb_check_var	= s3fb_check_var,
+	.fb_set_par	= s3fb_set_par,
+	.fb_setcolreg	= s3fb_setcolreg,
+	.fb_blank	= s3fb_blank,
+	.fb_pan_display	= s3fb_pan_display,
+	.fb_fillrect	= s3fb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= s3fb_imageblit,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static int __devinit s3_identification(int chip)
+{
+	if (chip == CHIP_XXX_TRIO) {
+		u8 cr30 = vga_rcrt(NULL, 0x30);
+		u8 cr2e = vga_rcrt(NULL, 0x2e);
+		u8 cr2f = vga_rcrt(NULL, 0x2f);
+
+		if ((cr30 == 0xE0) || (cr30 == 0xE1)) {
+			if (cr2e == 0x10)
+				return CHIP_732_TRIO32;
+			if (cr2e == 0x11) {
+				if (! (cr2f & 0x40))
+					return CHIP_764_TRIO64;
+				else
+					return CHIP_765_TRIO64VP;
+			}
+		}
+	}
+
+	if (chip == CHIP_XXX_TRIO64V2_DXGX) {
+		u8 cr6f = vga_rcrt(NULL, 0x6f);
+
+		if (! (cr6f & 0x01))
+			return CHIP_775_TRIO64V2_DX;
+		else
+			return CHIP_785_TRIO64V2_GX;
+	}
+
+	if (chip == CHIP_XXX_VIRGE_DXGX) {
+		u8 cr6f = vga_rcrt(NULL, 0x6f);
+
+		if (! (cr6f & 0x01))
+			return CHIP_375_VIRGE_DX;
+		else
+			return CHIP_385_VIRGE_GX;
+	}
+
+	return CHIP_UNKNOWN;
+}
+
+
+/* PCI probe */
+
+static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	struct fb_info *info;
+	struct s3fb_info *par;
+	int rc;
+	u8 regval, cr38, cr39;
+
+	/* Ignore secondary VGA device because there is no VGA arbitration */
+	if (! svga_primary_device(dev)) {
+		dev_info(&(dev->dev), "ignoring secondary device\n");
+		return -ENODEV;
+	}
+
+	/* Allocate and fill driver data structure */
+	info = framebuffer_alloc(sizeof(struct s3fb_info), NULL);
+	if (!info) {
+		dev_err(&(dev->dev), "cannot allocate memory\n");
+		return -ENOMEM;
+	}
+
+	par = info->par;
+	mutex_init(&par->open_lock);
+
+	info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
+	info->fbops = &s3fb_ops;
+
+	/* Prepare PCI device */
+	rc = pci_enable_device(dev);
+	if (rc < 0) {
+		dev_err(&(dev->dev), "cannot enable PCI device\n");
+		goto err_enable_device;
+	}
+
+	rc = pci_request_regions(dev, "s3fb");
+	if (rc < 0) {
+		dev_err(&(dev->dev), "cannot reserve framebuffer region\n");
+		goto err_request_regions;
+	}
+
+
+	info->fix.smem_start = pci_resource_start(dev, 0);
+	info->fix.smem_len = pci_resource_len(dev, 0);
+
+	/* Map physical IO memory address into kernel space */
+	info->screen_base = pci_iomap(dev, 0, 0);
+	if (! info->screen_base) {
+		rc = -ENOMEM;
+		dev_err(&(dev->dev), "iomap for framebuffer failed\n");
+		goto err_iomap;
+	}
+
+	/* Unlock regs */
+	cr38 = vga_rcrt(NULL, 0x38);
+	cr39 = vga_rcrt(NULL, 0x39);
+	vga_wseq(NULL, 0x08, 0x06);
+	vga_wcrt(NULL, 0x38, 0x48);
+	vga_wcrt(NULL, 0x39, 0xA5);
+
+	/* Find how many physical memory there is on card */
+	/* 0x36 register is accessible even if other registers are locked */
+	regval = vga_rcrt(NULL, 0x36);
+	info->screen_size = s3_memsizes[regval >> 5] << 10;
+	info->fix.smem_len = info->screen_size;
+
+	par->chip = id->driver_data & CHIP_MASK;
+	par->rev = vga_rcrt(NULL, 0x2f);
+	if (par->chip & CHIP_UNDECIDED_FLAG)
+		par->chip = s3_identification(par->chip);
+
+	/* Find MCLK frequency */
+	regval = vga_rseq(NULL, 0x10);
+	par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F)  + 2);
+	par->mclk_freq = par->mclk_freq >> (regval >> 5);
+
+	/* Restore locks */
+	vga_wcrt(NULL, 0x38, cr38);
+	vga_wcrt(NULL, 0x39, cr39);
+
+	strcpy(info->fix.id, s3_names [par->chip]);
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	info->fix.ypanstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->pseudo_palette = (void*) (par->pseudo_palette);
+
+	/* Prepare startup mode */
+	rc = fb_find_mode(&(info->var), info, mode, NULL, 0, NULL, 8);
+	if (! ((rc == 1) || (rc == 2))) {
+		rc = -EINVAL;
+		dev_err(&(dev->dev), "mode %s not found\n", mode);
+		goto err_find_mode;
+	}
+
+	rc = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (rc < 0) {
+		dev_err(&(dev->dev), "cannot allocate colormap\n");
+		goto err_alloc_cmap;
+	}
+
+	rc = register_framebuffer(info);
+	if (rc < 0) {
+		dev_err(&(dev->dev), "cannot register framebuffer\n");
+		goto err_reg_fb;
+	}
+
+	printk(KERN_INFO "fb%d: %s on %s, %d MB RAM, %d MHz MCLK\n", info->node, info->fix.id,
+		 pci_name(dev), info->fix.smem_len >> 20, (par->mclk_freq + 500) / 1000);
+
+	if (par->chip == CHIP_UNKNOWN)
+		printk(KERN_INFO "fb%d: unknown chip, CR2D=%x, CR2E=%x, CRT2F=%x, CRT30=%x\n",
+			info->node, vga_rcrt(NULL, 0x2d), vga_rcrt(NULL, 0x2e),
+			vga_rcrt(NULL, 0x2f), vga_rcrt(NULL, 0x30));
+
+	/* Record a reference to the driver data */
+	pci_set_drvdata(dev, info);
+
+#ifdef CONFIG_MTRR
+	if (mtrr) {
+		par->mtrr_reg = -1;
+		par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
+	}
+#endif
+
+	return 0;
+
+	/* Error handling */
+err_reg_fb:
+	fb_dealloc_cmap(&info->cmap);
+err_alloc_cmap:
+err_find_mode:
+	pci_iounmap(dev, info->screen_base);
+err_iomap:
+	pci_release_regions(dev);
+err_request_regions:
+/*	pci_disable_device(dev); */
+err_enable_device:
+	framebuffer_release(info);
+	return rc;
+}
+
+
+/* PCI remove */
+
+static void __devexit s3_pci_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct s3fb_info *par = info->par;
+
+	if (info) {
+
+#ifdef CONFIG_MTRR
+		if (par->mtrr_reg >= 0) {
+			mtrr_del(par->mtrr_reg, 0, 0);
+			par->mtrr_reg = -1;
+		}
+#endif
+
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+
+		pci_iounmap(dev, info->screen_base);
+		pci_release_regions(dev);
+/*		pci_disable_device(dev); */
+
+		pci_set_drvdata(dev, NULL);
+		framebuffer_release(info);
+	}
+}
+
+/* PCI suspend */
+
+static int s3_pci_suspend(struct pci_dev* dev, pm_message_t state)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct s3fb_info *par = info->par;
+
+	dev_info(&(dev->dev), "suspend\n");
+
+	acquire_console_sem();
+	mutex_lock(&(par->open_lock));
+
+	if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
+		mutex_unlock(&(par->open_lock));
+		release_console_sem();
+		return 0;
+	}
+
+	fb_set_suspend(info, 1);
+
+	pci_save_state(dev);
+	pci_disable_device(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
+
+	mutex_unlock(&(par->open_lock));
+	release_console_sem();
+
+	return 0;
+}
+
+
+/* PCI resume */
+
+static int s3_pci_resume(struct pci_dev* dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+	struct s3fb_info *par = info->par;
+
+	dev_info(&(dev->dev), "resume\n");
+
+	acquire_console_sem();
+	mutex_lock(&(par->open_lock));
+
+	if (par->ref_count == 0) {
+		mutex_unlock(&(par->open_lock));
+		release_console_sem();
+		return 0;
+	}
+
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+	pci_enable_device(dev);
+	pci_set_master(dev);
+
+	s3fb_set_par(info);
+	fb_set_suspend(info, 0);
+
+	mutex_unlock(&(par->open_lock));
+	release_console_sem();
+
+	return 0;
+}
+
+
+/* List of boards that we are trying to support */
+
+static struct pci_device_id s3_devices[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8810), .driver_data = CHIP_XXX_TRIO},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8811), .driver_data = CHIP_XXX_TRIO},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8812), .driver_data = CHIP_M65_AURORA64VP},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8814), .driver_data = CHIP_767_TRIO64UVP},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8901), .driver_data = CHIP_XXX_TRIO64V2_DXGX},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8902), .driver_data = CHIP_551_PLATO_PX},
+
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x5631), .driver_data = CHIP_325_VIRGE},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x883D), .driver_data = CHIP_988_VIRGE_VX},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A01), .driver_data = CHIP_XXX_VIRGE_DXGX},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P},
+	{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
+
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+
+MODULE_DEVICE_TABLE(pci, s3_devices);
+
+static struct pci_driver s3fb_pci_driver = {
+	.name		= "s3fb",
+	.id_table	= s3_devices,
+	.probe		= s3_pci_probe,
+	.remove		= __devexit_p(s3_pci_remove),
+	.suspend	= s3_pci_suspend,
+	.resume		= s3_pci_resume,
+};
+
+/* Parse user speficied options */
+
+#ifndef MODULE
+static int  __init s3fb_setup(char *options)
+{
+	char *opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((opt = strsep(&options, ",")) != NULL) {
+
+		if (!*opt)
+			continue;
+#ifdef CONFIG_MTRR
+		else if (!strcmp(opt, "mtrr:"))
+			mtrr = simple_strtoul(opt + 5, NULL, 0);
+#endif
+		else if (!strcmp(opt, "fasttext:"))
+			mtrr = simple_strtoul(opt + 9, NULL, 0);
+		else
+			mode = opt;
+	}
+
+	return 0;
+}
+#endif
+
+/* Cleanup */
+
+static void __exit s3fb_cleanup(void)
+{
+	pr_debug("s3fb: cleaning up\n");
+	pci_unregister_driver(&s3fb_pci_driver);
+}
+
+/* Driver Initialisation */
+
+static int __init s3fb_init(void)
+{
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("s3fb", &option))
+		return -ENODEV;
+	s3fb_setup(option);
+#endif
+
+	pr_debug("s3fb: initializing\n");
+	return pci_register_driver(&s3fb_pci_driver);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Modularization */
+
+module_init(s3fb_init);
+module_exit(s3fb_cleanup);
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 82b3dea..4afa305 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -833,7 +833,8 @@
 	vga_out8(0x3d5, cr66, par);
 }
 
-static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+static void savage_update_var(struct fb_var_screeninfo *var,
+			      const struct fb_videomode *modedb)
 {
 	var->xres = var->xres_virtual = modedb->xres;
 	var->yres = modedb->yres;
@@ -902,7 +903,7 @@
 	}
 
 	if (!mode_valid) {
-		struct fb_videomode *mode;
+		const struct fb_videomode *mode;
 
 		mode = fb_find_best_mode(var, &info->modelist);
 		if (mode) {
@@ -2206,11 +2207,10 @@
 			     info->monspecs.modedb, info->monspecs.modedb_len,
 			     NULL, 8);
 	} else if (info->monspecs.modedb != NULL) {
-		struct fb_videomode *modedb;
+		const struct fb_videomode *mode;
 
-		modedb = fb_find_best_display(&info->monspecs,
-					      &info->modelist);
-		savage_update_var(&info->var, modedb);
+		mode = fb_find_best_display(&info->monspecs, &info->modelist);
+		savage_update_var(&info->var, mode);
 	}
 
 	/* maximize virtual vertical length */
diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c
index 2ab3868..c311ad3 100644
--- a/drivers/video/sis/init.c
+++ b/drivers/video/sis/init.c
@@ -317,23 +317,23 @@
 }
 #endif
 
-BOOLEAN
+bool
 SiSInitPtr(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType < SIS_315H) {
 #ifdef SIS300
       InitTo300Pointer(SiS_Pr);
 #else
-      return FALSE;
+      return false;
 #endif
    } else {
 #ifdef SIS315H
       InitTo310Pointer(SiS_Pr);
 #else
-      return FALSE;
+      return false;
 #endif
    }
-   return TRUE;
+   return true;
 }
 
 /*********************************************/
@@ -345,7 +345,7 @@
 #endif
 unsigned short
 SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
-		int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
+		int Depth, bool FSTN, int LCDwidth, int LCDheight)
 {
    unsigned short ModeIndex = 0;
 
@@ -483,7 +483,7 @@
 
 unsigned short
 SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
-		int Depth, BOOLEAN FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
+		int Depth, bool FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
 		unsigned int VBFlags2)
 {
    unsigned short ModeIndex = 0;
@@ -873,7 +873,7 @@
 		break;
    }
 
-   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, FALSE, 0, 0);
+   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, false, 0, 0);
 }
 
 
@@ -1020,12 +1020,12 @@
 
    /* 661 and newer: NEVER write non-zero to SR11[7:4] */
    /* (SR11 is used for DDC and in enable/disablebridge) */
-   SiS_Pr->SiS_SensibleSR11 = FALSE;
+   SiS_Pr->SiS_SensibleSR11 = false;
    SiS_Pr->SiS_MyCR63 = 0x63;
    if(SiS_Pr->ChipType >= SIS_330) {
       SiS_Pr->SiS_MyCR63 = 0x53;
       if(SiS_Pr->ChipType >= SIS_661) {
-         SiS_Pr->SiS_SensibleSR11 = TRUE;
+         SiS_Pr->SiS_SensibleSR11 = true;
       }
    }
 
@@ -1253,7 +1253,7 @@
 /*        HELPER: Determine ROM usage        */
 /*********************************************/
 
-BOOLEAN
+bool
 SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
 {
    unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
@@ -1261,16 +1261,16 @@
 
    if(SiS_Pr->ChipType >= XGI_20) {
       /* XGI ROMs don't qualify */
-      return FALSE;
+      return false;
    } else if(SiS_Pr->ChipType >= SIS_761) {
       /* I very much assume 761, 340 and newer will use new layout */
-      return TRUE;
+      return true;
    } else if(SiS_Pr->ChipType >= SIS_661) {
       if((ROMAddr[0x1a] == 'N') &&
 	 (ROMAddr[0x1b] == 'e') &&
 	 (ROMAddr[0x1c] == 'w') &&
 	 (ROMAddr[0x1d] == 'V')) {
-	 return TRUE;
+	 return true;
       }
       romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
       if(romversoffs) {
@@ -1280,17 +1280,17 @@
 	 }
       }
       if((romvmaj != 0) || (romvmin >= 92)) {
-	 return TRUE;
+	 return true;
       }
    } else if(IS_SIS650740) {
       if((ROMAddr[0x1a] == 'N') &&
 	 (ROMAddr[0x1b] == 'e') &&
 	 (ROMAddr[0x1c] == 'w') &&
 	 (ROMAddr[0x1d] == 'V')) {
-	 return TRUE;
+	 return true;
       }
    }
-   return FALSE;
+   return false;
 }
 
 static void
@@ -1299,8 +1299,8 @@
    unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
    unsigned short romptr = 0;
 
-   SiS_Pr->SiS_UseROM = FALSE;
-   SiS_Pr->SiS_ROMNew = FALSE;
+   SiS_Pr->SiS_UseROM = false;
+   SiS_Pr->SiS_ROMNew = false;
    SiS_Pr->SiS_PWDOffset = 0;
 
    if(SiS_Pr->ChipType >= XGI_20) return;
@@ -1312,15 +1312,15 @@
 	  * of the BIOS image.
 	  */
 	 if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
-	    SiS_Pr->SiS_UseROM = TRUE;
+	    SiS_Pr->SiS_UseROM = true;
       } else if(SiS_Pr->ChipType < SIS_315H) {
 	 /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
 	  * the others do as well
 	  */
-	 SiS_Pr->SiS_UseROM = TRUE;
+	 SiS_Pr->SiS_UseROM = true;
       } else {
 	 /* 315/330 series stick to the standard(s) */
-	 SiS_Pr->SiS_UseROM = TRUE;
+	 SiS_Pr->SiS_UseROM = true;
 	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
 	    SiS_Pr->SiS_EMIOffset = 14;
 	    SiS_Pr->SiS_PWDOffset = 17;
@@ -1488,7 +1488,7 @@
 /*********************************************/
 
 #ifdef SIS_LINUX_KERNEL
-static BOOLEAN
+static bool
 SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 		unsigned short ModeIdIndex)
 {
@@ -1496,10 +1496,10 @@
    unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
    unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
 
-   if(!AdapterMemSize) return TRUE;
+   if(!AdapterMemSize) return true;
 
-   if(AdapterMemSize < memorysize) return FALSE;
-   return TRUE;
+   if(AdapterMemSize < memorysize) return false;
+   return true;
 }
 #endif
 
@@ -1605,7 +1605,7 @@
 /*           HELPER: SearchModeID            */
 /*********************************************/
 
-BOOLEAN
+bool
 SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
 		unsigned short *ModeIdIndex)
 {
@@ -1617,7 +1617,7 @@
 
       for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
 	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
-	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return FALSE;
+	 if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return false;
       }
 
       if((*ModeNo) == 0x07) {
@@ -1635,11 +1635,11 @@
 
       for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
 	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
-	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return FALSE;
+	 if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return false;
       }
 
    }
-   return TRUE;
+   return true;
 }
 
 /*********************************************/
@@ -1696,13 +1696,13 @@
 /*           HELPER: LowModeTests            */
 /*********************************************/
 
-static BOOLEAN
+static bool
 SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
    unsigned short temp, temp1, temp2;
 
    if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
-      return TRUE;
+      return true;
    temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
    SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
    temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
@@ -1712,13 +1712,13 @@
    SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
    if((SiS_Pr->ChipType >= SIS_315H) ||
       (SiS_Pr->ChipType == SIS_300)) {
-      if(temp2 == 0x55) return FALSE;
-      else return TRUE;
+      if(temp2 == 0x55) return false;
+      else return true;
    } else {
-      if(temp2 != 0x55) return TRUE;
+      if(temp2 != 0x55) return true;
       else {
 	 SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
-	 return FALSE;
+	 return false;
       }
    }
 }
@@ -3237,14 +3237,14 @@
 SiS_SetPitch(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
 {
    SISPtr pSiS = SISPTR(pScrn);
-   BOOLEAN isslavemode = FALSE;
+   bool isslavemode = false;
 
    if( (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) &&
        ( ((pSiS->VGAEngine == SIS_300_VGA) &&
 	  (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
 	 ((pSiS->VGAEngine == SIS_315_VGA) &&
 	  (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
-      isslavemode = TRUE;
+      isslavemode = true;
    }
 
    /* We need to set pitch for CRT1 if bridge is in slave mode, too */
@@ -3264,10 +3264,10 @@
 
 #ifdef SIS_XORG_XF86
 /* We need pScrn for setting the pitch correctly */
-BOOLEAN
-SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, BOOLEAN dosetpitch)
+bool
+SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, bool dosetpitch)
 #else
-BOOLEAN
+bool
 SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 #endif
 {
@@ -3277,8 +3277,8 @@
 #ifdef SIS_LINUX_KERNEL
    unsigned short KeepLockReg;
 
-   SiS_Pr->UseCustomMode = FALSE;
-   SiS_Pr->CRT1UsesCustomMode = FALSE;
+   SiS_Pr->UseCustomMode = false;
+   SiS_Pr->CRT1UsesCustomMode = false;
 #endif
 
    SiS_Pr->SiS_flag_clearbuffer = 0;
@@ -3317,7 +3317,7 @@
    SiS_UnLockCRT2(SiS_Pr);
 
    if(!SiS_Pr->UseCustomMode) {
-      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
    } else {
       ModeIdIndex = 0;
    }
@@ -3347,18 +3347,18 @@
 #ifdef SIS_LINUX_KERNEL
    /* Check memory size (kernel framebuffer driver only) */
    if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
-      return FALSE;
+      return false;
    }
 #endif
 
    SiS_OpenCRTC(SiS_Pr);
 
    if(SiS_Pr->UseCustomMode) {
-      SiS_Pr->CRT1UsesCustomMode = TRUE;
+      SiS_Pr->CRT1UsesCustomMode = true;
       SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
       SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
    } else {
-      SiS_Pr->CRT1UsesCustomMode = FALSE;
+      SiS_Pr->CRT1UsesCustomMode = false;
    }
 
    /* Set mode on CRT1 */
@@ -3445,7 +3445,7 @@
    if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
 #endif
 
-   return TRUE;
+   return true;
 }
 
 /*********************************************/
@@ -3454,14 +3454,14 @@
 /*********************************************/
 
 #ifdef SIS_XORG_XF86
-BOOLEAN
+bool
 SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-               DisplayModePtr mode, BOOLEAN IsCustom)
+               DisplayModePtr mode, bool IsCustom)
 {
    SISPtr pSiS = SISPTR(pScrn);
    unsigned short ModeNo = 0;
 
-   SiS_Pr->UseCustomMode = FALSE;
+   SiS_Pr->UseCustomMode = false;
 
    if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
 
@@ -3475,13 +3475,13 @@
 
       /* Don't need vbflags here; checks done earlier */
       ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
-      if(!ModeNo) return FALSE;
+      if(!ModeNo) return false;
 
       xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
 
    }
 
-   return(SiSSetMode(SiS_Pr, pScrn, ModeNo, TRUE));
+   return(SiSSetMode(SiS_Pr, pScrn, ModeNo, true));
 }
 
 /*********************************************/
@@ -3489,9 +3489,9 @@
 /*           for Dual-Head modes             */
 /*********************************************/
 
-BOOLEAN
+bool
 SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-               DisplayModePtr mode, BOOLEAN IsCustom)
+               DisplayModePtr mode, bool IsCustom)
 {
    SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
    SISPtr  pSiS = SISPTR(pScrn);
@@ -3502,7 +3502,7 @@
    unsigned short ModeNo = 0;
    unsigned char  backupreg = 0;
 
-   SiS_Pr->UseCustomMode = FALSE;
+   SiS_Pr->UseCustomMode = false;
 
    /* Remember: Custom modes for CRT2 are ONLY supported
     *     -) on the 30x/B/C, and
@@ -3516,7 +3516,7 @@
    } else {
 
 	 ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
-	 if(!ModeNo) return FALSE;
+	 if(!ModeNo) return false;
 
    }
 
@@ -3550,10 +3550,10 @@
       if(pSiSEnt->CRT1ModeNo == -1) {
 	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
 		"Setting CRT2 mode delayed until after setting CRT1 mode\n");
-	 return TRUE;
+	 return true;
       }
 #endif
-      pSiSEnt->CRT2ModeSet = TRUE;
+      pSiSEnt->CRT2ModeSet = true;
    }
 #endif
 
@@ -3578,7 +3578,7 @@
    SiS_UnLockCRT2(SiS_Pr);
 
    if(!SiS_Pr->UseCustomMode) {
-      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
    } else {
       ModeIdIndex = 0;
    }
@@ -3658,7 +3658,7 @@
 
    SiS_Handle760(SiS_Pr);
 
-   return TRUE;
+   return true;
 }
 
 /*********************************************/
@@ -3666,9 +3666,9 @@
 /*           for Dual-Head modes             */
 /*********************************************/
 
-BOOLEAN
+bool
 SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-                   DisplayModePtr mode, BOOLEAN IsCustom)
+                   DisplayModePtr mode, bool IsCustom)
 {
    SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
    SISPtr  pSiS = SISPTR(pScrn);
@@ -3677,10 +3677,10 @@
 #ifdef SISDUALHEAD
    SISEntPtr pSiSEnt = pSiS->entityPrivate;
    unsigned char  backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
-   BOOLEAN backupcustom;
+   bool backupcustom;
 #endif
 
-   SiS_Pr->UseCustomMode = FALSE;
+   SiS_Pr->UseCustomMode = false;
 
    if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
 
@@ -3697,7 +3697,7 @@
    } else {
 
 	 ModeNo = SiS_GetModeNumber(pScrn, mode, 0); /* don't give VBFlags */
-	 if(!ModeNo) return FALSE;
+	 if(!ModeNo) return false;
 
 	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
 	 	"Setting standard mode 0x%x on CRT1\n", ModeNo);
@@ -3721,7 +3721,7 @@
    SiS_UnLockCRT2(SiS_Pr);
 
    if(!SiS_Pr->UseCustomMode) {
-      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+      if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
    } else {
       ModeIdIndex = 0;
    }
@@ -3771,11 +3771,11 @@
 #endif
 
    if(SiS_Pr->UseCustomMode) {
-      SiS_Pr->CRT1UsesCustomMode = TRUE;
+      SiS_Pr->CRT1UsesCustomMode = true;
       SiS_Pr->CSRClock_CRT1 = SiS_Pr->CSRClock;
       SiS_Pr->CModeFlag_CRT1 = SiS_Pr->CModeFlag;
    } else {
-      SiS_Pr->CRT1UsesCustomMode = FALSE;
+      SiS_Pr->CRT1UsesCustomMode = false;
    }
 
    /* Reset CRT2 if changing mode on CRT1 */
@@ -3838,7 +3838,7 @@
    /* Backup/Set ModeNo in BIOS scratch area */
    SiS_GetSetModeID(pScrn,ModeNo);
 
-   return TRUE;
+   return true;
 }
 #endif /* Linux_XF86 */
 
@@ -4082,7 +4082,7 @@
 			DisplayModePtr current
 #endif
 #ifdef SIS_LINUX_KERNEL
-			struct fb_var_screeninfo *var, BOOLEAN writeres
+			struct fb_var_screeninfo *var, bool writeres
 #endif
 )
 {
diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h
index 59d1284..f40a680 100644
--- a/drivers/video/sis/init.h
+++ b/drivers/video/sis/init.h
@@ -1521,13 +1521,13 @@
    0x00}}
 };
 
-BOOLEAN		SiSInitPtr(struct SiS_Private *SiS_Pr);
+bool		SiSInitPtr(struct SiS_Private *SiS_Pr);
 #ifdef SIS_XORG_XF86
 unsigned short	SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
-				int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
+				int Depth, bool FSTN, int LCDwith, int LCDheight);
 #endif
 unsigned short	SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, BOOLEAN FSTN,
+				int VDisplay, int Depth, bool FSTN,
 				unsigned short CustomT, int LCDwith, int LCDheight,
 				unsigned int VBFlags2);
 unsigned short	SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
@@ -1558,12 +1558,12 @@
 void		SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
 unsigned short	SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex);
-BOOLEAN		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+bool		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
 #ifndef SIS_LINUX_KERNEL
 void		SiS_GetVBType(struct SiS_Private *SiS_Pr);
 #endif
 
-BOOLEAN		SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+bool		SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
 				unsigned short *ModeIdIndex);
 unsigned short	SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex);
@@ -1581,17 +1581,17 @@
 #endif
 void		SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
 #ifdef SIS_XORG_XF86
-BOOLEAN		SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
-				BOOLEAN dosetpitch);
-BOOLEAN		SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-				DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN		SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-				DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN		SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
-				DisplayModePtr mode, BOOLEAN IsCustom);
+bool		SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
+				bool dosetpitch);
+bool		SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+				DisplayModePtr mode, bool IsCustom);
+bool		SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+				DisplayModePtr mode, bool IsCustom);
+bool		SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+				DisplayModePtr mode, bool IsCustom);
 #endif
 #ifdef SIS_LINUX_KERNEL
-BOOLEAN		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+bool		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 #endif
 void		SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
 void		SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
@@ -1602,7 +1602,7 @@
 #endif
 #ifdef SIS_LINUX_KERNEL
 void		SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
-				int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
+				int yres, struct fb_var_screeninfo *var, bool writeres);
 #endif
 
 /* From init301.c: */
@@ -1615,7 +1615,7 @@
 				unsigned short ModeIdIndex);
 extern void		SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
 extern void		SiS_DisableBridge(struct SiS_Private *);
-extern BOOLEAN		SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
+extern bool		SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
 extern unsigned short	SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex);
 extern void		SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
@@ -1624,8 +1624,8 @@
 extern unsigned short	SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
 extern unsigned short	SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex, unsigned short RRTI);
-extern BOOLEAN		SiS_IsVAMode(struct SiS_Private *);
-extern BOOLEAN		SiS_IsDualEdge(struct SiS_Private *);
+extern bool		SiS_IsVAMode(struct SiS_Private *);
+extern bool		SiS_IsDualEdge(struct SiS_Private *);
 
 #ifdef SIS_XORG_XF86
 /* From other modules: */
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c
index 47e1896..da33d80 100644
--- a/drivers/video/sis/init301.c
+++ b/drivers/video/sis/init301.c
@@ -200,7 +200,7 @@
 /*           Adjust Rate for CRT2            */
 /*********************************************/
 
-static BOOLEAN
+static bool
 SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RRTI, unsigned short *i)
 {
@@ -269,7 +269,7 @@
    /* Look backwards in table for matching CRT2 mode */
    for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
       infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
-      if(infoflag & checkmask) return TRUE;
+      if(infoflag & checkmask) return true;
       if((*i) == 0) break;
    }
 
@@ -279,9 +279,9 @@
    for((*i) = 0; ; (*i)++) {
       if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
       infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
-      if(infoflag & checkmask) return TRUE;
+      if(infoflag & checkmask) return true;
    }
-   return FALSE;
+   return false;
 }
 
 /*********************************************/
@@ -405,7 +405,7 @@
 /*********************************************/
 
 #ifdef SIS300
-static BOOLEAN
+static bool
 SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
 {
    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
@@ -415,13 +415,13 @@
       if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 	 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
 	 temp1 = SISGETROMW(0x23b);
-	 if(temp1 & temp) return TRUE;
+	 if(temp1 & temp) return true;
       }
    }
-   return FALSE;
+   return false;
 }
 
-static BOOLEAN
+static bool
 SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
 {
    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
@@ -431,10 +431,10 @@
       if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
 	 temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
 	 temp1 = SISGETROMW(0x23d);
-	 if(temp1 & temp) return TRUE;
+	 if(temp1 & temp) return true;
       }
    }
-   return FALSE;
+   return false;
 }
 #endif
 
@@ -687,38 +687,38 @@
 /*********************************************/
 
 #ifdef SIS300
-static BOOLEAN
+static bool
 SiS_Is301B(struct SiS_Private *SiS_Pr)
 {
-   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
-   return FALSE;
+   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return true;
+   return false;
 }
 #endif
 
-static BOOLEAN
+static bool
 SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType == SIS_730) {
-      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return true;
    }
-   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return TRUE;
-   return FALSE;
+   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return true;
+   return false;
 }
 
-BOOLEAN
+bool
 SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
    if(SiS_Pr->ChipType >= SIS_315H) {
       if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
-	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return TRUE;
+	 if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return true;
       }
    }
 #endif
-   return FALSE;
+   return false;
 }
 
-BOOLEAN
+bool
 SiS_IsVAMode(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
@@ -726,70 +726,70 @@
 
    if(SiS_Pr->ChipType >= SIS_315H) {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
+      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return true;
    }
 #endif
-   return FALSE;
+   return false;
 }
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
 {
-   if(SiS_IsVAMode(SiS_Pr))  return TRUE;
-   if(SiS_CRT2IsLCD(SiS_Pr)) return TRUE;
-   return FALSE;
+   if(SiS_IsVAMode(SiS_Pr))  return true;
+   if(SiS_CRT2IsLCD(SiS_Pr)) return true;
+   return false;
 }
 #endif
 
-static BOOLEAN
+static bool
 SiS_IsDualLink(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
    if(SiS_Pr->ChipType >= SIS_315H) {
       if((SiS_CRT2IsLCD(SiS_Pr)) ||
          (SiS_IsVAMode(SiS_Pr))) {
-	 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
+	 if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return true;
       }
    }
 #endif
-   return FALSE;
+   return false;
 }
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_TVEnabled(struct SiS_Private *SiS_Pr)
 {
-   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
+   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return true;
    if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
-      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
 {
-   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
-   return FALSE;
+   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return true;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
 {
    if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
@@ -798,90 +798,90 @@
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
       /* Check for revision != A0 only */
       if((flag == 0xe0) || (flag == 0xc0) ||
-         (flag == 0xb0) || (flag == 0x90)) return FALSE;
-   } else if(SiS_Pr->ChipType >= SIS_661) return FALSE;
-   return TRUE;
+         (flag == 0xb0) || (flag == 0x90)) return false;
+   } else if(SiS_Pr->ChipType >= SIS_661) return false;
+   return true;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType >= SIS_315H) {
       /* YPrPb = 0x08 */
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsChScart(struct SiS_Private *SiS_Pr)
 {
    if(SiS_Pr->ChipType >= SIS_315H) {
       /* Scart = 0x04 */
-      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return TRUE;
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
 
    if(SiS_Pr->ChipType >= SIS_315H) {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToTV)        return TRUE;
+      if(flag & SetCRT2ToTV)        return true;
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      if(flag & EnableCHYPbPr)      return TRUE;  /* = YPrPb = 0x08 */
-      if(flag & EnableCHScart)      return TRUE;  /* = Scart = 0x04 - TW */
+      if(flag & EnableCHYPbPr)      return true;  /* = YPrPb = 0x08 */
+      if(flag & EnableCHScart)      return true;  /* = Scart = 0x04 - TW */
    } else {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToTV)        return TRUE;
+      if(flag & SetCRT2ToTV)        return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
 #ifdef SIS315H
-static BOOLEAN
+static bool
 SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
 
    if(SiS_Pr->ChipType >= SIS_315H) {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToLCD) return TRUE;
+      if(flag & SetCRT2ToLCD) return true;
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-      if(flag & SetToLCDA)    return TRUE;
+      if(flag & SetToLCDA)    return true;
    } else {
       flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-      if(flag & SetCRT2ToLCD) return TRUE;
+      if(flag & SetCRT2ToLCD) return true;
    }
-   return FALSE;
+   return false;
 }
 #endif
 
-static BOOLEAN
+static bool
 SiS_HaveBridge(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
 
    if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-      return TRUE;
+      return true;
    } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
       flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-      if((flag == 1) || (flag == 2)) return TRUE;
+      if((flag == 1) || (flag == 2)) return true;
    }
-   return FALSE;
+   return false;
 }
 
-static BOOLEAN
+static bool
 SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag;
@@ -890,23 +890,23 @@
       flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
       if(SiS_Pr->ChipType < SIS_315H) {
 	flag &= 0xa0;
-	if((flag == 0x80) || (flag == 0x20)) return TRUE;
+	if((flag == 0x80) || (flag == 0x20)) return true;
       } else {
 	flag &= 0x50;
-	if((flag == 0x40) || (flag == 0x10)) return TRUE;
+	if((flag == 0x40) || (flag == 0x10)) return true;
       }
    }
-   return FALSE;
+   return false;
 }
 
-static BOOLEAN
+static bool
 SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
 {
    unsigned short flag1;
 
    flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
-   if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
-   return FALSE;
+   if(flag1 & (SetInSlaveMode >> 8)) return true;
+   return false;
 }
 
 /*********************************************/
@@ -1461,11 +1461,11 @@
 
    if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
       if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
-	 SiS_Pr->SiS_NeedRomModeData = TRUE;
+	 SiS_Pr->SiS_NeedRomModeData = true;
 	 SiS_Pr->PanelHT  = temp;
       }
       if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
-	 SiS_Pr->SiS_NeedRomModeData = TRUE;
+	 SiS_Pr->SiS_NeedRomModeData = true;
 	 SiS_Pr->PanelVT  = temp;
       }
       SiS_Pr->PanelHRS = SISGETROMW(10);
@@ -1516,7 +1516,7 @@
 SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
   unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
-  BOOLEAN panelcanscale = FALSE;
+  bool panelcanscale = false;
 #ifdef SIS300
   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
   static const unsigned char SiS300SeriesLCDRes[] =
@@ -1534,10 +1534,10 @@
   SiS_Pr->PanelHRE        = 999; /* HSync end */
   SiS_Pr->PanelVRS        = 999; /* VSync start */
   SiS_Pr->PanelVRE        = 999; /* VSync end */
-  SiS_Pr->SiS_NeedRomModeData = FALSE;
+  SiS_Pr->SiS_NeedRomModeData = false;
 
   /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
-  SiS_Pr->Alternate1600x1200 = FALSE;
+  SiS_Pr->Alternate1600x1200 = false;
 
   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
 
@@ -1633,7 +1633,7 @@
       SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
   }
 
-  panelcanscale = (SiS_Pr->SiS_LCDInfo & DontExpandLCD) ? TRUE : FALSE;
+  panelcanscale = (bool)(SiS_Pr->SiS_LCDInfo & DontExpandLCD);
 
   if(!SiS_Pr->UsePanelScaler)          SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
   else if(SiS_Pr->UsePanelScaler == 1) SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
@@ -1833,7 +1833,7 @@
 				  SiS_Pr->PanelHRS =   48; SiS_Pr->PanelHRE =   32;
 				  SiS_Pr->PanelVRS =    2; SiS_Pr->PanelVRE =    4;
 				  SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
-				  SiS_Pr->Alternate1600x1200 = TRUE;
+				  SiS_Pr->Alternate1600x1200 = true;
 			       }
 			    } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
 			       SiS_Pr->PanelHT  = 2048; SiS_Pr->PanelVT  = 1320;
@@ -3448,7 +3448,7 @@
 
      } else {
 
-	BOOLEAN gotit = FALSE;
+	bool gotit = false;
 
 	if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
 
@@ -3456,7 +3456,7 @@
 	   SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
 	   SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
 	   SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
-	   gotit = TRUE;
+	   gotit = true;
 
 	} else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
 
@@ -3474,7 +3474,7 @@
 	      if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
 	      else                         SiS_Pr->SiS_RVBHRS2 += tempax;
 	   }
-	   if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
+	   if(SiS_Pr->SiS_VGAHT) gotit = true;
 	   else {
 	      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
 	      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
@@ -3485,7 +3485,7 @@
 	      SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
 	      SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
 	      SiS_Pr->SiS_RVBHRS2 = 0;
-	      gotit = TRUE;
+	      gotit = true;
 	   }
 #endif
 
@@ -3960,8 +3960,8 @@
 #ifdef SIS315H	   /* 315 series */
 
 	   int didpwd = 0;
-	   BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	                      (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
+	   bool custom1 = (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+	                  (SiS_Pr->SiS_CustomT == CUT_CLEVO1400);
 
 	   modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
 
@@ -4313,7 +4313,7 @@
   unsigned short temp=0, tempah;
 #ifdef SIS315H
   unsigned short temp1, pushax=0;
-  BOOLEAN delaylong = FALSE;
+  bool delaylong = false;
 #endif
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
@@ -4448,7 +4448,7 @@
 
 	    if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
 	       SiS_PanelDelayLoop(SiS_Pr, 3, 10);
-	       delaylong = TRUE;
+	       delaylong = true;
 	    }
 
 	 }
@@ -4530,7 +4530,7 @@
 			SiS_Pr->EMI_33 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 2];
 			if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
 			/* emidelay = SISGETROMW((romptr + 0x22)); */
-			SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = TRUE;
+			SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = true;
 		     }
 		  }
 
@@ -4644,7 +4644,7 @@
 			SiS_PanelDelayLoop(SiS_Pr, 3, 5);
 			if(delaylong) {
 			   SiS_PanelDelayLoop(SiS_Pr, 3, 5);
-			   delaylong = FALSE;
+			   delaylong = false;
 			}
 			SiS_WaitVBRetrace(SiS_Pr);
 			SiS_WaitVBRetrace(SiS_Pr);
@@ -5454,7 +5454,7 @@
   unsigned short modeflag, resinfo = 0;
   unsigned short push2, tempax, tempbx, tempcx, temp;
   unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 0;
-  BOOLEAN islvds = FALSE, issis  = FALSE, chkdclkfirst = FALSE;
+  bool islvds = false, issis  = false, chkdclkfirst = false;
 #ifdef SIS300
   unsigned short crt2crtc = 0;
 #endif
@@ -5480,17 +5480,17 @@
 
   /* is lvds if really LVDS, or 301B-DH with external LVDS transmitter */
   if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
-     islvds = TRUE;
+     islvds = true;
   }
 
   /* is really sis if sis bridge, but not 301B-DH */
   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-     issis = TRUE;
+     issis = true;
   }
 
   if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-        chkdclkfirst = TRUE;
+        chkdclkfirst = true;
      }
   }
 
@@ -6447,13 +6447,13 @@
    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xeb,temp);
 }
 
-static BOOLEAN
+static bool
 SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
 		    unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
 		    unsigned short *ResIndex)
 {
 
-  if(SiS_Pr->ChipType < SIS_315H) return FALSE;
+  if(SiS_Pr->ChipType < SIS_315H) return false;
 
   if(ModeNo <= 0x13)
      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -6688,7 +6688,7 @@
   unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
   unsigned short push2, modeflag, crt2crtc, bridgeoffset;
   unsigned int   longtemp, PhaseIndex;
-  BOOLEAN        newtvphase;
+  bool           newtvphase;
   const unsigned char *TimingPoint;
 #ifdef SIS315H
   unsigned short resindex, CRT2Index;
@@ -6721,11 +6721,11 @@
   PhaseIndex  = 0x01; /* SiS_PALPhase */
   TimingPoint = SiS_Pr->SiS_PALTiming;
 
-  newtvphase = FALSE;
+  newtvphase = false;
   if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
       ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
 	(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-     newtvphase = TRUE;
+     newtvphase = true;
   }
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
@@ -7754,13 +7754,13 @@
 /*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
 /*********************************************/
 
-static BOOLEAN
+static bool
 SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
 		   unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
 		   unsigned short *DisplayType)
  {
   unsigned short modeflag = 0;
-  BOOLEAN checkhd = TRUE;
+  bool checkhd = true;
 
   /* Pass 1:1 not supported here */
 
@@ -7792,7 +7792,7 @@
      (*DisplayType = 0);
      switch(SiS_Pr->SiS_LCDResInfo) {
      case Panel_320x240_1: (*DisplayType) = 50;
-			   checkhd = FALSE;
+			   checkhd = false;
 			   break;
      case Panel_320x240_2: (*DisplayType) = 14;
 			   break;
@@ -7802,7 +7802,7 @@
 			   break;
      case Panel_1024x600:  (*DisplayType) = 26;
 			   break;
-     default: return TRUE;
+     default: return true;
      }
 
      if(checkhd) {
@@ -7815,7 +7815,7 @@
 
   }
 
-  return TRUE;
+  return true;
 }
 
 static void
@@ -8654,7 +8654,7 @@
 /*      MAIN: SET CRT2 REGISTER GROUP        */
 /*********************************************/
 
-BOOLEAN
+bool
 SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
 #ifdef SIS300
@@ -8690,7 +8690,7 @@
    if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
       SiS_LockCRT2(SiS_Pr);
       SiS_DisplayOn(SiS_Pr);
-      return TRUE;
+      return true;
    }
 
    SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
@@ -8828,7 +8828,7 @@
       SiS_LockCRT2(SiS_Pr);
    }
 
-   return TRUE;
+   return true;
 }
 
 
@@ -8908,7 +8908,7 @@
   return NULL;
 }
 
-static BOOLEAN
+static bool
 SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
 {
   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;  		/* DAB (Device Address Byte) */
@@ -8921,14 +8921,14 @@
 
   while(*dataptr) {
      dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
-     if(!dataptr) return FALSE;
+     if(!dataptr) return false;
   }
 #ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
   xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
 #endif
 #endif
-  return TRUE;
+  return true;
 }
 #endif
 
@@ -8939,7 +8939,7 @@
  * 0x0a, possibly for working around the DDC problems
  */
 
-static BOOLEAN
+static bool
 SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
 {
   unsigned short temp, i;
@@ -8958,9 +8958,9 @@
      if(temp) continue;							/*    (ERROR: no ack) */
      if(SiS_SetStop(SiS_Pr)) continue;					/* Set stop condition */
      SiS_Pr->SiS_ChrontelInit = 1;
-     return TRUE;
+     return true;
   }
-  return FALSE;
+  return false;
 }
 
 /* Write to Chrontel 700x */
@@ -9119,7 +9119,7 @@
 #endif
 unsigned short
 SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
-                unsigned short adaptnum, unsigned short DDCdatatype, BOOLEAN checkcr32,
+                unsigned short adaptnum, unsigned short DDCdatatype, bool checkcr32,
 		unsigned int VBFlags2)
 {
      unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
@@ -9287,7 +9287,7 @@
 {
     unsigned char mask, value;
     unsigned short  temp, ret=0;
-    BOOLEAN failed = FALSE;
+    bool failed = false;
 
     SiS_SetSwitchDDC2(SiS_Pr);
     if(SiS_PrepareDDC(SiS_Pr)) {
@@ -9308,7 +9308,7 @@
            mask = 0xff;
 	   value = 0xff;
        } else {
-           failed = TRUE;
+           failed = true;
 	   ret = 0xFFFF;
 #ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
@@ -9317,7 +9317,7 @@
 #endif
        }
     }
-    if(failed == FALSE) {
+    if(!failed) {
        temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
        SiS_SendACK(SiS_Pr, 1);
        temp &= mask;
@@ -9431,7 +9431,7 @@
    if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
       return 0xFFFF;
 
-   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE, VBFlags2) == 0xFFFF)
+   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, false, VBFlags2) == 0xFFFF)
       return 0xFFFF;
 
    sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
@@ -9829,7 +9829,7 @@
 {
   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
   unsigned short delay=0,index,myindex,temp,romptr=0;
-  BOOLEAN dochiptest = TRUE;
+  bool dochiptest = true;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x20,0xbf);
@@ -9864,7 +9864,7 @@
 
   } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD|SetCRT2ToLCDA)) {  /* ----------	LCD/LCDA */
 
-     BOOLEAN gotitfrompci = FALSE;
+     bool gotitfrompci = false;
 
      /* Could we detect a PDC for LCD or did we get a user-defined? If yes, use it */
 
@@ -9916,22 +9916,22 @@
      case CUT_COMPAQ1280:
      case CUT_COMPAQ12802:
 	if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-	   gotitfrompci = TRUE;
-	   dochiptest = FALSE;
+	   gotitfrompci = true;
+	   dochiptest = false;
 	   delay = 0x03;
 	}
 	break;
      case CUT_CLEVO1400:
      case CUT_CLEVO14002:
-	gotitfrompci = TRUE;
-	dochiptest = FALSE;
+	gotitfrompci = true;
+	dochiptest = false;
 	delay = 0x02;
 	break;
      case CUT_CLEVO1024:
      case CUT_CLEVO10242:
         if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-	   gotitfrompci = TRUE;
-	   dochiptest = FALSE;
+	   gotitfrompci = true;
+	   dochiptest = false;
 	   delay = 0x33;
 	   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2D,delay);
 	   delay &= 0x0f;
@@ -10009,7 +10009,7 @@
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
 	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
-	dochiptest = FALSE;
+	dochiptest = false;
      }
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {			/* ------------ TV */
@@ -10043,12 +10043,12 @@
 	   case CUT_CLEVO1400:
 	   case CUT_CLEVO14002:
 	      delay = 0x02;
-	      dochiptest = FALSE;
+	      dochiptest = false;
 	      break;
 	   case CUT_CLEVO1024:
 	   case CUT_CLEVO10242:
 	      delay = 0x03;
-	      dochiptest = FALSE;
+	      dochiptest = false;
    	      break;
 	   default:
               delay = SiS310_TVDelayCompensation_651301LV[index];
@@ -10085,7 +10085,7 @@
 
      if(SiS_LCDAEnabled(SiS_Pr)) {
 	delay &= 0x0f;
-	dochiptest = FALSE;
+	dochiptest = false;
      }
 
   } else return;
@@ -10728,7 +10728,7 @@
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1c,0x00);
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1d,0x1b);
 	   }
-	   if((SiS_Pr->Backup == TRUE) && (SiS_Pr->Backup_Mode == ModeNo)) {
+	   if(SiS_Pr->Backup && (SiS_Pr->Backup_Mode == ModeNo)) {
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,SiS_Pr->Backup_14);
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,SiS_Pr->Backup_15);
 	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,SiS_Pr->Backup_16);
diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h
index 4f3a286..7708e1e 100644
--- a/drivers/video/sis/init301.h
+++ b/drivers/video/sis/init301.h
@@ -363,8 +363,8 @@
 void		SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
 unsigned short	SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
 void		SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
-BOOLEAN		SiS_IsDualEdge(struct SiS_Private *SiS_Pr);
-BOOLEAN		SiS_IsVAMode(struct SiS_Private *SiS_Pr);
+bool		SiS_IsDualEdge(struct SiS_Private *SiS_Pr);
+bool		SiS_IsVAMode(struct SiS_Private *SiS_Pr);
 void		SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 			unsigned short ModeIdIndex, int checkcrt2mode);
 void		SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
@@ -379,7 +379,7 @@
 #ifndef SIS_LINUX_KERNEL
 void		SiS_EnableBridge(struct SiS_Private *SiS_Pr);
 #endif
-BOOLEAN		SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+bool		SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 void		SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
 void		SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
 
@@ -403,7 +403,7 @@
 #endif /* 315 */
 
 #ifdef SIS300
-static  BOOLEAN	SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
+static  bool	SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
 void		SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
 #endif
 
@@ -416,14 +416,14 @@
 #ifdef SIS_XORG_XF86
 unsigned short		SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
 				int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
-				BOOLEAN checkcr32, unsigned int VBFlags2);
+				bool checkcr32, unsigned int VBFlags2);
 unsigned short		SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
 unsigned short		SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
 				unsigned char *buffer);
 #else
 static unsigned short	SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
 				int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
-				BOOLEAN checkcr32, unsigned int VBFlags2);
+				bool checkcr32, unsigned int VBFlags2);
 static unsigned short	SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
 static unsigned short	SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
 				unsigned char *buffer);
@@ -469,7 +469,7 @@
 extern void		SiS_SetRegAND(SISIOADDRESS, unsigned short, unsigned short);
 extern void		SiS_DisplayOff(struct SiS_Private *SiS_Pr);
 extern void		SiS_DisplayOn(struct SiS_Private *SiS_Pr);
-extern BOOLEAN		SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
+extern bool		SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
 extern unsigned short	SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
 				unsigned short ModeIdIndex);
 extern unsigned short	SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
index c3884a2..47a3350 100644
--- a/drivers/video/sis/initextlfb.c
+++ b/drivers/video/sis/initextlfb.c
@@ -38,14 +38,14 @@
 			unsigned char modeno, unsigned char rateindex);
 int		sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
 			unsigned char rateindex, struct fb_var_screeninfo *var);
-BOOLEAN		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+bool		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
 			int *htotal, int *vtotal, unsigned char rateindex);
 
-extern BOOLEAN	SiSInitPtr(struct SiS_Private *SiS_Pr);
-extern BOOLEAN	SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+extern bool	SiSInitPtr(struct SiS_Private *SiS_Pr);
+extern bool	SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
 			unsigned short *ModeIdIndex);
 extern void	SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
-			int xres, int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
+			int xres, int yres, struct fb_var_screeninfo *var, bool writeres);
 
 int
 sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
@@ -131,7 +131,7 @@
 			(unsigned char *)&SiS_Pr->SiS_CRT1Table[index].CR[0],
 			SiS_Pr->SiS_RefIndex[RRTI].XRes,
 			SiS_Pr->SiS_RefIndex[RRTI].YRes,
-			var, FALSE);
+			var, false);
 
     if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x8000)
        var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
@@ -175,7 +175,7 @@
     return 1;
 }
 
-BOOLEAN
+bool
 sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal,
 			int *vtotal, unsigned char rateindex)
 {
@@ -184,7 +184,7 @@
     unsigned short RRTI = 0;
     unsigned char  sr_data, cr_data, cr_data2;
 
-    if(!SiSInitPtr(SiS_Pr)) return FALSE;
+    if(!SiSInitPtr(SiS_Pr)) return false;
 
     if(rateindex > 0) rateindex--;
 
@@ -195,7 +195,7 @@
     }
 #endif
 
-    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return false;
 
     RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
     if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
@@ -226,7 +226,7 @@
     if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & InterlaceMode)
        *vtotal *= 2;
 
-    return TRUE;
+    return true;
 }
 
 
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index a259446..7d5ee21 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -526,7 +526,7 @@
 		u16 vmax;
 		u32 dclockmax;
 		u8  feature;
-		BOOLEAN datavalid;
+		bool datavalid;
 	}		sisfb_thismonitor;
 
 	unsigned short	chip_id;	/* PCI ID of chip */
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index baaf495..01197d7 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -110,7 +110,7 @@
 /* ------------- Parameter parsing -------------- */
 
 static void __devinit
-sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
+sisfb_search_vesamode(unsigned int vesamode, bool quiet)
 {
 	int i = 0, j = 0;
 
@@ -150,7 +150,7 @@
 }
 
 static void __devinit
-sisfb_search_mode(char *name, BOOLEAN quiet)
+sisfb_search_mode(char *name, bool quiet)
 {
 	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
 	int i = 0;
@@ -251,7 +251,7 @@
 			"sisfb: Using vga mode %s pre-set by kernel as default\n",
 			mymode);
 
-		sisfb_search_mode(mymode, TRUE);
+		sisfb_search_mode(mymode, true);
 	}
 #endif
 	return;
@@ -307,7 +307,7 @@
 sisfb_search_specialtiming(const char *name)
 {
 	int i = 0;
-	BOOLEAN found = FALSE;
+	bool found = false;
 
 	/* We don't know the hardware specs yet and there is no ivideo */
 
@@ -322,7 +322,7 @@
 			if(!strnicmp(name,mycustomttable[i].optionName,
 			   strlen(mycustomttable[i].optionName))) {
 				sisfb_specialtiming = mycustomttable[i].SpecialID;
-				found = TRUE;
+				found = true;
 				printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
 					mycustomttable[i].vendorName,
 					mycustomttable[i].cardName,
@@ -353,7 +353,7 @@
 {
 	unsigned char *biosver = NULL;
 	unsigned char *biosdate = NULL;
-	BOOLEAN footprint;
+	bool footprint;
 	u32 chksum = 0;
 	int i, j;
 
@@ -380,16 +380,16 @@
 		      (mycustomttable[i].bioschksum == chksum)))		&&
 		    (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
 		    (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
-			footprint = TRUE;
+			footprint = true;
 			for(j = 0; j < 5; j++) {
 				if(mycustomttable[i].biosFootprintAddr[j]) {
 					if(ivideo->SiS_Pr.UseROM) {
 						if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
 							mycustomttable[i].biosFootprintData[j]) {
-							footprint = FALSE;
+							footprint = false;
 						}
 					} else
-						footprint = FALSE;
+						footprint = false;
 				}
 			}
 			if(footprint) {
@@ -406,7 +406,7 @@
 	} while(mycustomttable[i].chipID);
 }
 
-static BOOLEAN __devinit
+static bool __devinit
 sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
 {
 	int i, j, xres, yres, refresh, index;
@@ -417,13 +417,13 @@
 	   buffer[4] != 0xff || buffer[5] != 0xff ||
 	   buffer[6] != 0xff || buffer[7] != 0x00) {
 		printk(KERN_DEBUG "sisfb: Bad EDID header\n");
-		return FALSE;
+		return false;
 	}
 
 	if(buffer[0x12] != 0x01) {
 		printk(KERN_INFO "sisfb: EDID version %d not supported\n",
 			buffer[0x12]);
-		return FALSE;
+		return false;
 	}
 
 	monitor->feature = buffer[0x18];
@@ -449,7 +449,7 @@
 		  monitor->vmin = buffer[j + 5];
 		  monitor->vmax = buffer[j + 6];
 		  monitor->dclockmax = buffer[j + 9] * 10 * 1000;
-		  monitor->datavalid = TRUE;
+		  monitor->datavalid = true;
 		  break;
 	       }
 	       j += 18;
@@ -501,7 +501,7 @@
 	      index += 2;
 	   }
 	   if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
-	      monitor->datavalid = TRUE;
+	      monitor->datavalid = true;
 	   }
 	}
 
@@ -514,7 +514,7 @@
 	unsigned short temp, i, realcrtno = crtno;
 	unsigned char  buffer[256];
 
-	monitor->datavalid = FALSE;
+	monitor->datavalid = false;
 
 	if(crtno) {
 	   if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
@@ -563,7 +563,7 @@
 
 /* -------------- Mode validation --------------- */
 
-static BOOLEAN
+static bool
 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
 		int mode_idx, int rate_idx, int rate)
 {
@@ -571,10 +571,10 @@
 	unsigned int dclock, hsync;
 
 	if(!monitor->datavalid)
-		return TRUE;
+		return true;
 
 	if(mode_idx < 0)
-		return FALSE;
+		return false;
 
 	/* Skip for 320x200, 320x240, 640x400 */
 	switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
@@ -587,34 +587,34 @@
 	case 0x2f:
 	case 0x5d:
 	case 0x5e:
-		return TRUE;
+		return true;
 #ifdef CONFIG_FB_SIS_315
 	case 0x5a:
 	case 0x5b:
-		if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE;
+		if(ivideo->sisvga_engine == SIS_315_VGA) return true;
 #endif
 	}
 
 	if(rate < (monitor->vmin - 1))
-		return FALSE;
+		return false;
 	if(rate > (monitor->vmax + 1))
-		return FALSE;
+		return false;
 
 	if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
 				  sisbios_mode[mode_idx].mode_no[ivideo->mni],
 				  &htotal, &vtotal, rate_idx)) {
 		dclock = (htotal * vtotal * rate) / 1000;
 		if(dclock > (monitor->dclockmax + 1000))
-			return FALSE;
+			return false;
 		hsync = dclock / htotal;
 		if(hsync < (monitor->hmin - 1))
-			return FALSE;
+			return false;
 		if(hsync > (monitor->hmax + 1))
-			return FALSE;
+			return false;
         } else {
-		return FALSE;
+		return false;
 	}
-	return TRUE;
+	return true;
 }
 
 static int
@@ -732,49 +732,49 @@
 	}
 }
 
-static BOOLEAN
+static bool
 sisfb_bridgeisslave(struct sis_video_info *ivideo)
 {
 	unsigned char P1_00;
 
 	if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
-		return FALSE;
+		return false;
 
 	inSISIDXREG(SISPART1,0x00,P1_00);
 	if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
 	    ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
-		return TRUE;
+		return true;
 	} else {
-		return FALSE;
+		return false;
 	}
 }
 
-static BOOLEAN
+static bool
 sisfballowretracecrt1(struct sis_video_info *ivideo)
 {
 	u8 temp;
 
 	inSISIDXREG(SISCR,0x17,temp);
 	if(!(temp & 0x80))
-		return FALSE;
+		return false;
 
 	inSISIDXREG(SISSR,0x1f,temp);
 	if(temp & 0xc0)
-		return FALSE;
+		return false;
 
-	return TRUE;
+	return true;
 }
 
-static BOOLEAN
+static bool
 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
 {
 	if(!sisfballowretracecrt1(ivideo))
-		return FALSE;
+		return false;
 
 	if(inSISREG(SISINPSTAT) & 0x08)
-		return TRUE;
+		return true;
 	else
-		return FALSE;
+		return false;
 }
 
 static void
@@ -791,7 +791,7 @@
 	while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
 }
 
-static BOOLEAN
+static bool
 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
 {
 	unsigned char temp, reg;
@@ -799,17 +799,17 @@
 	switch(ivideo->sisvga_engine) {
 	case SIS_300_VGA: reg = 0x25; break;
 	case SIS_315_VGA: reg = 0x30; break;
-	default:	  return FALSE;
+	default:	  return false;
 	}
 
 	inSISIDXREG(SISPART1, reg, temp);
 	if(temp & 0x02)
-		return TRUE;
+		return true;
 	else
-		return FALSE;
+		return false;
 }
 
-static BOOLEAN
+static bool
 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
 {
 	if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
@@ -874,7 +874,7 @@
 sisfb_myblank(struct sis_video_info *ivideo, int blank)
 {
 	u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
-	BOOLEAN backlight = TRUE;
+	bool backlight = true;
 
 	switch(blank) {
 		case FB_BLANK_UNBLANK:	/* on */
@@ -884,7 +884,7 @@
 			cr63  = 0x00;
 			p2_0  = 0x20;
 			p1_13 = 0x00;
-			backlight = TRUE;
+			backlight = true;
 			break;
 		case FB_BLANK_NORMAL:	/* blank */
 			sr01  = 0x20;
@@ -893,7 +893,7 @@
 			cr63  = 0x00;
 			p2_0  = 0x20;
 			p1_13 = 0x00;
-			backlight = TRUE;
+			backlight = true;
 			break;
 		case FB_BLANK_VSYNC_SUSPEND:	/* no vsync */
 			sr01  = 0x20;
@@ -902,7 +902,7 @@
 			cr63  = 0x40;
 			p2_0  = 0x40;
 			p1_13 = 0x80;
-			backlight = FALSE;
+			backlight = false;
 			break;
 		case FB_BLANK_HSYNC_SUSPEND:	/* no hsync */
 			sr01  = 0x20;
@@ -911,7 +911,7 @@
 			cr63  = 0x40;
 			p2_0  = 0x80;
 			p1_13 = 0x40;
-			backlight = FALSE;
+			backlight = false;
 			break;
 		case FB_BLANK_POWERDOWN:	/* off */
 			sr01  = 0x20;
@@ -920,7 +920,7 @@
 			cr63  = 0x40;
 			p2_0  = 0xc0;
 			p1_13 = 0xc0;
-			backlight = FALSE;
+			backlight = false;
 			break;
 		default:
 			return 1;
@@ -1109,11 +1109,11 @@
 static void
 sisfb_set_pitch(struct sis_video_info *ivideo)
 {
-	BOOLEAN isslavemode = FALSE;
+	bool isslavemode = false;
 	unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
 	unsigned short HDisplay2 = ivideo->video_linelength >> 3;
 
-	if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
+	if(sisfb_bridgeisslave(ivideo)) isslavemode = true;
 
 	/* We need to set pitch for CRT1 if bridge is in slave mode, too */
 	if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
@@ -1178,7 +1178,7 @@
 
 	sisfb_pre_setmode(ivideo);
 
-	if(SiSSetMode(&ivideo->SiS_Pr, modeno) == 0) {
+	if(!SiSSetMode(&ivideo->SiS_Pr, modeno)) {
 		printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
 		return -EINVAL;
 	}
@@ -1446,7 +1446,7 @@
 	unsigned int drate = 0, hrate = 0, maxyres;
 	int found_mode = 0;
 	int refresh_rate, search_idx, tidx;
-	BOOLEAN recalc_clock = FALSE;
+	bool recalc_clock = false;
 	u32 pixclock;
 
 	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
@@ -1524,7 +1524,7 @@
 	    (var->bits_per_pixel == 8) ) {
 		/* Slave modes on LVDS and 301B-DH */
 		refresh_rate = 60;
-		recalc_clock = TRUE;
+		recalc_clock = true;
 	} else if( (ivideo->current_htotal == htotal) &&
 		   (ivideo->current_vtotal == vtotal) &&
 		   (ivideo->current_pixclock == pixclock) ) {
@@ -1545,17 +1545,17 @@
 		} else {
 			refresh_rate = 60;
 		}
-		recalc_clock = TRUE;
+		recalc_clock = true;
 	} else if((pixclock) && (htotal) && (vtotal)) {
 		drate = 1000000000 / pixclock;
 		hrate = (drate * 1000) / htotal;
 		refresh_rate = (unsigned int) (hrate * 2 / vtotal);
 	} else if(ivideo->current_refresh_rate) {
 		refresh_rate = ivideo->current_refresh_rate;
-		recalc_clock = TRUE;
+		recalc_clock = true;
 	} else {
 		refresh_rate = 60;
-		recalc_clock = TRUE;
+		recalc_clock = true;
 	}
 
 	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
@@ -2181,7 +2181,7 @@
 
 /* ------------------ Sensing routines ------------------ */
 
-static BOOLEAN __devinit
+static bool __devinit
 sisfb_test_DDC1(struct sis_video_info *ivideo)
 {
     unsigned short old;
@@ -2191,13 +2191,13 @@
     do {
 	if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
     } while(count--);
-    return (count == -1) ? FALSE : TRUE;
+    return (count != -1);
 }
 
 static void __devinit
 sisfb_sense_crt1(struct sis_video_info *ivideo)
 {
-    BOOLEAN mustwait = FALSE;
+    bool mustwait = false;
     u8  sr1F, cr17;
 #ifdef CONFIG_FB_SIS_315
     u8  cr63=0;
@@ -2208,7 +2208,7 @@
     inSISIDXREG(SISSR,0x1F,sr1F);
     orSISIDXREG(SISSR,0x1F,0x04);
     andSISIDXREG(SISSR,0x1F,0x3F);
-    if(sr1F & 0xc0) mustwait = TRUE;
+    if(sr1F & 0xc0) mustwait = true;
 
 #ifdef CONFIG_FB_SIS_315
     if(ivideo->sisvga_engine == SIS_315_VGA) {
@@ -2222,7 +2222,7 @@
     cr17 &= 0x80;
     if(!cr17) {
        orSISIDXREG(SISCR,0x17,0x80);
-       mustwait = TRUE;
+       mustwait = true;
        outSISIDXREG(SISSR, 0x00, 0x01);
        outSISIDXREG(SISSR, 0x00, 0x03);
     }
@@ -2284,7 +2284,7 @@
 	u8 reg, cr37 = 0, paneltype = 0;
 	u16 xres, yres;
 
-	ivideo->SiS_Pr.PanelSelfDetected = FALSE;
+	ivideo->SiS_Pr.PanelSelfDetected = false;
 
 	/* LCD detection only for TMDS bridges */
 	if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
@@ -2361,7 +2361,7 @@
 	setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
 	orSISIDXREG(SISCR, 0x32, 0x08);
 
-	ivideo->SiS_Pr.PanelSelfDetected = TRUE;
+	ivideo->SiS_Pr.PanelSelfDetected = true;
 }
 
 static int __devinit
@@ -3016,7 +3016,7 @@
 			int tmp;
 			inSISIDXREG(SISPART1,0x13,tmp);
 			if(tmp & 0x04) {
-				ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
+				ivideo->SiS_Pr.SiS_UseLCDA = true;
 				ivideo->detectedlcda = 0x03;
 			}
 		}
@@ -3071,9 +3071,9 @@
 				inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
 				inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
 				inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
-				ivideo->SiS_Pr.HaveEMI = TRUE;
+				ivideo->SiS_Pr.HaveEMI = true;
 				if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
-					ivideo->SiS_Pr.HaveEMILCD = TRUE;
+					ivideo->SiS_Pr.HaveEMILCD = true;
 				}
 			}
 		}
@@ -3558,8 +3558,8 @@
 	}
 #endif
 
-	SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
-	SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
 	ivideo->curFSTN = ivideo->curDSTN = 0;
 
 	switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
@@ -3814,8 +3814,8 @@
 static void
 sisfb_post_setmode(struct sis_video_info *ivideo)
 {
-	BOOLEAN crt1isoff = FALSE;
-	BOOLEAN doit = TRUE;
+	bool crt1isoff = false;
+	bool doit = true;
 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
 	u8 reg;
 #endif
@@ -3834,17 +3834,17 @@
 
 	/* We can't switch off CRT1 if bridge is in slave mode */
 	if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
-		if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
+		if(sisfb_bridgeisslave(ivideo)) doit = false;
 	} else
 		ivideo->sisfb_crt1off = 0;
 
 #ifdef CONFIG_FB_SIS_300
 	if(ivideo->sisvga_engine == SIS_300_VGA) {
 		if((ivideo->sisfb_crt1off) && (doit)) {
-			crt1isoff = TRUE;
+			crt1isoff = true;
 			reg = 0x00;
 		} else {
-			crt1isoff = FALSE;
+			crt1isoff = false;
 			reg = 0x80;
 		}
 		setSISIDXREG(SISCR, 0x17, 0x7f, reg);
@@ -3853,11 +3853,11 @@
 #ifdef CONFIG_FB_SIS_315
 	if(ivideo->sisvga_engine == SIS_315_VGA) {
 		if((ivideo->sisfb_crt1off) && (doit)) {
-			crt1isoff = TRUE;
+			crt1isoff = true;
 			reg  = 0x40;
 			reg1 = 0xc0;
 		} else {
-			crt1isoff = FALSE;
+			crt1isoff = false;
 			reg  = 0x00;
 			reg1 = 0x00;
 		}
@@ -4004,9 +4004,9 @@
 		} else if(!strnicmp(this_opt, "tvstandard:",11)) {
 			sisfb_search_tvstd(this_opt + 11);
 		} else if(!strnicmp(this_opt, "mode:", 5)) {
-			sisfb_search_mode(this_opt + 5, FALSE);
+			sisfb_search_mode(this_opt + 5, false);
 		} else if(!strnicmp(this_opt, "vesa:", 5)) {
-			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE);
+			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
 		} else if(!strnicmp(this_opt, "rate:", 5)) {
 			sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
 		} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
@@ -4062,7 +4062,7 @@
 			   sisfb_lvdshl = temp;
 			}
 		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
-			sisfb_search_mode(this_opt, TRUE);
+			sisfb_search_mode(this_opt, true);
 #if !defined(__i386__) && !defined(__x86_64__)
 		} else if(!strnicmp(this_opt, "resetcard", 9)) {
 			sisfb_resetcard = 1;
@@ -4564,9 +4564,9 @@
 	sisfb_sense_crt1(ivideo);
 
 	/* Set default mode, don't clear screen */
-	ivideo->SiS_Pr.SiS_UseOEM = FALSE;
-	SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
-	SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+	ivideo->SiS_Pr.SiS_UseOEM = false;
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
 	ivideo->curFSTN = ivideo->curDSTN = 0;
 	ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
 	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
@@ -5680,9 +5680,9 @@
 	} else {
 
 		/* Set default mode, don't clear screen */
-		ivideo->SiS_Pr.SiS_UseOEM = FALSE;
-		SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
-		SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+		ivideo->SiS_Pr.SiS_UseOEM = false;
+		SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+		SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
 		ivideo->curFSTN = ivideo->curDSTN = 0;
 		ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
 		SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
@@ -5723,9 +5723,9 @@
 	}
 
 	/* Set default mode, don't clear screen */
-	ivideo->SiS_Pr.SiS_UseOEM = FALSE;
-	SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
-	SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+	ivideo->SiS_Pr.SiS_UseOEM = false;
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, false);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, false);
 	ivideo->curFSTN = ivideo->curDSTN = 0;
 	SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
 
@@ -5819,7 +5819,7 @@
 	ivideo->detectedpdca = 0xff;
 	ivideo->detectedlcda = 0xff;
 
-	ivideo->sisfb_thismonitor.datavalid = FALSE;
+	ivideo->sisfb_thismonitor.datavalid = false;
 
 	ivideo->current_base = 0;
 
@@ -5871,21 +5871,21 @@
 
 	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
 	ivideo->SiS_Pr.SiS_CHOverScan = -1;
-	ivideo->SiS_Pr.SiS_ChSW = FALSE;
-	ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
-	ivideo->SiS_Pr.HaveEMI = FALSE;
-	ivideo->SiS_Pr.HaveEMILCD = FALSE;
-	ivideo->SiS_Pr.OverruleEMI = FALSE;
-	ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE;
+	ivideo->SiS_Pr.SiS_ChSW = false;
+	ivideo->SiS_Pr.SiS_UseLCDA = false;
+	ivideo->SiS_Pr.HaveEMI = false;
+	ivideo->SiS_Pr.HaveEMILCD = false;
+	ivideo->SiS_Pr.OverruleEMI = false;
+	ivideo->SiS_Pr.SiS_SensibleSR11 = false;
 	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
 	ivideo->SiS_Pr.PDC  = -1;
 	ivideo->SiS_Pr.PDCA = -1;
-	ivideo->SiS_Pr.DDCPortMixup = FALSE;
+	ivideo->SiS_Pr.DDCPortMixup = false;
 #ifdef CONFIG_FB_SIS_315
 	if(ivideo->chip >= SIS_330) {
 		ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
 		if(ivideo->chip >= SIS_661) {
-			ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
+			ivideo->SiS_Pr.SiS_SensibleSR11 = true;
 		}
 	}
 #endif
@@ -5969,7 +5969,7 @@
         	do {
 			if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
 			   mychswtable[i].subsysCard   == ivideo->subsysdevice) {
-				ivideo->SiS_Pr.SiS_ChSW = TRUE;
+				ivideo->SiS_Pr.SiS_ChSW = true;
 				printk(KERN_DEBUG "sisfb: Identified [%s %s] "
 					"requiring Chrontel/GPIO setup\n",
 					mychswtable[i].vendorName,
@@ -6018,20 +6018,20 @@
 	/* Search and copy ROM image */
 	ivideo->bios_abase = NULL;
 	ivideo->SiS_Pr.VirtualRomBase = NULL;
-	ivideo->SiS_Pr.UseROM = FALSE;
-	ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE;
+	ivideo->SiS_Pr.UseROM = false;
+	ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = false;
 	if(ivideo->sisfb_userom) {
 		ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
 		ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
-		ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE;
+		ivideo->SiS_Pr.UseROM = (bool)(ivideo->SiS_Pr.VirtualRomBase);
 		printk(KERN_INFO "sisfb: Video ROM %sfound\n",
 			ivideo->SiS_Pr.UseROM ? "" : "not ");
 		if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
-		   ivideo->SiS_Pr.UseROM = FALSE;
-		   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE;
+		   ivideo->SiS_Pr.UseROM = false;
+		   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = true;
 		   if( (ivideo->revision_id == 2) &&
 		       (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
-			ivideo->SiS_Pr.DDCPortMixup = TRUE;
+			ivideo->SiS_Pr.DDCPortMixup = true;
 		   }
 		}
 	} else {
@@ -6677,9 +6677,9 @@
 		sisfb_search_tvstd(tvstandard);
 
 	if(mode)
-		sisfb_search_mode(mode, FALSE);
+		sisfb_search_mode(mode, false);
 	else if(vesa != -1)
-		sisfb_search_vesamode(vesa, FALSE);
+		sisfb_search_vesamode(vesa, false);
 
 	sisfb_crt1off = (crt1off == 0) ? 1 : 0;
 
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index 88e4f1e..3e3b7fa 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -411,54 +411,54 @@
 	u16 xres;
 	u16 yres;
 	u16 refresh;
-	BOOLEAN SiS730valid32bpp;
+	bool SiS730valid32bpp;
 } sisfb_vrate[] = {
-	{1,  320,  200,  70,  TRUE},
-	{1,  320,  240,  60,  TRUE},
-	{1,  400,  300,  60,  TRUE},
-	{1,  512,  384,  60,  TRUE},
-	{1,  640,  400,  72,  TRUE},
-	{1,  640,  480,  60,  TRUE}, {2,  640,  480,  72,  TRUE}, {3,  640,  480,  75,  TRUE},
-	{4,  640,  480,  85,  TRUE}, {5,  640,  480, 100,  TRUE}, {6,  640,  480, 120,  TRUE},
-	{7,  640,  480, 160,  TRUE}, {8,  640,  480, 200,  TRUE},
-	{1,  720,  480,  60,  TRUE},
-	{1,  720,  576,  58,  TRUE},
-	{1,  768,  576,  58,  TRUE},
-	{1,  800,  480,  60,  TRUE}, {2,  800,  480,  75,  TRUE}, {3,  800,  480,  85,  TRUE},
-	{1,  800,  600,  56,  TRUE}, {2,  800,  600,  60,  TRUE}, {3,  800,  600,  72,  TRUE},
-	{4,  800,  600,  75,  TRUE}, {5,  800,  600,  85,  TRUE}, {6,  800,  600, 105,  TRUE},
-	{7,  800,  600, 120,  TRUE}, {8,  800,  600, 160,  TRUE},
-	{1,  848,  480,  39,  TRUE}, {2,  848,  480,  60,  TRUE},
-	{1,  856,  480,  39,  TRUE}, {2,  856,  480,  60,  TRUE},
-	{1,  960,  540,  60,  TRUE},
-	{1,  960,  600,  60,  TRUE},
-	{1, 1024,  576,  60,  TRUE}, {2, 1024,  576,  75,  TRUE}, {3, 1024,  576,  85,  TRUE},
-	{1, 1024,  600,  60,  TRUE},
-	{1, 1024,  768,  43,  TRUE}, {2, 1024,  768,  60,  TRUE}, {3, 1024,  768,  70, FALSE},
-	{4, 1024,  768,  75, FALSE}, {5, 1024,  768,  85,  TRUE}, {6, 1024,  768, 100,  TRUE},
-	{7, 1024,  768, 120,  TRUE},
-	{1, 1152,  768,  60,  TRUE},
-	{1, 1152,  864,  60,  TRUE}, {2, 1152,  864,  75,  TRUE}, {3, 1152,  864,  84,  TRUE},
-	{1, 1280,  720,  60,  TRUE}, {2, 1280,  720,  75,  TRUE}, {3, 1280,  720,  85,  TRUE},
-	{1, 1280,  768,  60,  TRUE},
-	{1, 1280,  800,  60,  TRUE},
-	{1, 1280,  854,  60,  TRUE},
-	{1, 1280,  960,  60,  TRUE}, {2, 1280,  960,  85,  TRUE},
-	{1, 1280, 1024,  43,  TRUE}, {2, 1280, 1024,  60,  TRUE}, {3, 1280, 1024,  75,  TRUE},
-	{4, 1280, 1024,  85,  TRUE},
-	{1, 1360,  768,  60,  TRUE},
-	{1, 1360, 1024,  59,  TRUE},
-	{1, 1400, 1050,  60,  TRUE}, {2, 1400, 1050,  75,  TRUE},
-	{1, 1600, 1200,  60,  TRUE}, {2, 1600, 1200,  65,  TRUE}, {3, 1600, 1200,  70,  TRUE},
-	{4, 1600, 1200,  75,  TRUE}, {5, 1600, 1200,  85,  TRUE}, {6, 1600, 1200, 100,  TRUE},
-	{7, 1600, 1200, 120,  TRUE},
-	{1, 1680, 1050,  60,  TRUE},
-	{1, 1920, 1080,  30,  TRUE},
-	{1, 1920, 1440,  60,  TRUE}, {2, 1920, 1440,  65,  TRUE}, {3, 1920, 1440,  70,  TRUE},
-	{4, 1920, 1440,  75,  TRUE}, {5, 1920, 1440,  85,  TRUE}, {6, 1920, 1440, 100,  TRUE},
-	{1, 2048, 1536,  60,  TRUE}, {2, 2048, 1536,  65,  TRUE}, {3, 2048, 1536,  70,  TRUE},
-	{4, 2048, 1536,  75,  TRUE}, {5, 2048, 1536,  85,  TRUE},
-	{0,    0,    0,   0, FALSE}
+	{1,  320,  200,  70,  true},
+	{1,  320,  240,  60,  true},
+	{1,  400,  300,  60,  true},
+	{1,  512,  384,  60,  true},
+	{1,  640,  400,  72,  true},
+	{1,  640,  480,  60,  true}, {2,  640,  480,  72,  true}, {3,  640,  480,  75,  true},
+	{4,  640,  480,  85,  true}, {5,  640,  480, 100,  true}, {6,  640,  480, 120,  true},
+	{7,  640,  480, 160,  true}, {8,  640,  480, 200,  true},
+	{1,  720,  480,  60,  true},
+	{1,  720,  576,  58,  true},
+	{1,  768,  576,  58,  true},
+	{1,  800,  480,  60,  true}, {2,  800,  480,  75,  true}, {3,  800,  480,  85,  true},
+	{1,  800,  600,  56,  true}, {2,  800,  600,  60,  true}, {3,  800,  600,  72,  true},
+	{4,  800,  600,  75,  true}, {5,  800,  600,  85,  true}, {6,  800,  600, 105,  true},
+	{7,  800,  600, 120,  true}, {8,  800,  600, 160,  true},
+	{1,  848,  480,  39,  true}, {2,  848,  480,  60,  true},
+	{1,  856,  480,  39,  true}, {2,  856,  480,  60,  true},
+	{1,  960,  540,  60,  true},
+	{1,  960,  600,  60,  true},
+	{1, 1024,  576,  60,  true}, {2, 1024,  576,  75,  true}, {3, 1024,  576,  85,  true},
+	{1, 1024,  600,  60,  true},
+	{1, 1024,  768,  43,  true}, {2, 1024,  768,  60,  true}, {3, 1024,  768,  70, false},
+	{4, 1024,  768,  75, false}, {5, 1024,  768,  85,  true}, {6, 1024,  768, 100,  true},
+	{7, 1024,  768, 120,  true},
+	{1, 1152,  768,  60,  true},
+	{1, 1152,  864,  60,  true}, {2, 1152,  864,  75,  true}, {3, 1152,  864,  84,  true},
+	{1, 1280,  720,  60,  true}, {2, 1280,  720,  75,  true}, {3, 1280,  720,  85,  true},
+	{1, 1280,  768,  60,  true},
+	{1, 1280,  800,  60,  true},
+	{1, 1280,  854,  60,  true},
+	{1, 1280,  960,  60,  true}, {2, 1280,  960,  85,  true},
+	{1, 1280, 1024,  43,  true}, {2, 1280, 1024,  60,  true}, {3, 1280, 1024,  75,  true},
+	{4, 1280, 1024,  85,  true},
+	{1, 1360,  768,  60,  true},
+	{1, 1360, 1024,  59,  true},
+	{1, 1400, 1050,  60,  true}, {2, 1400, 1050,  75,  true},
+	{1, 1600, 1200,  60,  true}, {2, 1600, 1200,  65,  true}, {3, 1600, 1200,  70,  true},
+	{4, 1600, 1200,  75,  true}, {5, 1600, 1200,  85,  true}, {6, 1600, 1200, 100,  true},
+	{7, 1600, 1200, 120,  true},
+	{1, 1680, 1050,  60,  true},
+	{1, 1920, 1080,  30,  true},
+	{1, 1920, 1440,  60,  true}, {2, 1920, 1440,  65,  true}, {3, 1920, 1440,  70,  true},
+	{4, 1920, 1440,  75,  true}, {5, 1920, 1440,  85,  true}, {6, 1920, 1440, 100,  true},
+	{1, 2048, 1536,  60,  true}, {2, 2048, 1536,  65,  true}, {3, 2048, 1536,  70,  true},
+	{4, 2048, 1536,  75,  true}, {5, 2048, 1536,  85,  true},
+	{0,    0,    0,   0, false}
 };
 
 static struct _sisfbddcsmodes {
@@ -691,7 +691,7 @@
 extern void	sisfb_syncaccel(struct sis_video_info *ivideo);
 
 /* Internal general routines */
-static void	sisfb_search_mode(char *name, BOOLEAN quiet);
+static void	sisfb_search_mode(char *name, bool quiet);
 static int	sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
 static u8	sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
 				int index);
@@ -702,10 +702,10 @@
 				struct fb_info *info);
 static void	sisfb_pre_setmode(struct sis_video_info *ivideo);
 static void	sisfb_post_setmode(struct sis_video_info *ivideo);
-static BOOLEAN	sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
-static BOOLEAN	sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
-static BOOLEAN	sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
-static BOOLEAN	sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static bool	sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static bool	sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static bool	sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static bool	sisfb_bridgeisslave(struct sis_video_info *ivideo);
 static void	sisfb_detect_VB_connect(struct sis_video_info *ivideo);
 static void	sisfb_get_VB_type(struct sis_video_info *ivideo);
 static void	sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
@@ -737,20 +737,20 @@
 
 /* Routines from init.c/init301.c */
 extern unsigned short	SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
-				int VDisplay, int Depth, BOOLEAN FSTN, unsigned short CustomT,
+				int VDisplay, int Depth, bool FSTN, unsigned short CustomT,
 				int LCDwith, int LCDheight, unsigned int VBFlags2);
 extern unsigned short	SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
 				int VDisplay, int Depth, unsigned int VBFlags2);
 extern unsigned short	SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
 				int VDisplay, int Depth, unsigned int VBFlags2);
 extern void		SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-extern BOOLEAN		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern bool		SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 extern void		SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
 extern void		SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
 
-extern BOOLEAN		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+extern bool		SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
 
-extern BOOLEAN		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+extern bool		sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
 				int *htotal, int *vtotal, unsigned char rateindex);
 extern int		sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
 				unsigned char modeno, unsigned char rateindex);
diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/sis/vgatypes.h
index 05d08b7..b532fbd 100644
--- a/drivers/video/sis/vgatypes.h
+++ b/drivers/video/sis/vgatypes.h
@@ -57,18 +57,6 @@
 #include <linux/version.h>
 #endif
 
-#ifndef FALSE
-#define FALSE   0
-#endif
-
-#ifndef TRUE
-#define TRUE    1
-#endif
-
-#ifndef BOOLEAN
-typedef unsigned int BOOLEAN;
-#endif
-
 #define SISIOMEMTYPE
 
 #ifdef SIS_LINUX_KERNEL
diff --git a/drivers/video/sis/vstruct.h b/drivers/video/sis/vstruct.h
index 9ae3292..705c853 100644
--- a/drivers/video/sis/vstruct.h
+++ b/drivers/video/sis/vstruct.h
@@ -240,7 +240,7 @@
 	void				*ivideo;
 #endif
 	unsigned char 			*VirtualRomBase;
-	BOOLEAN				UseROM;
+	bool				UseROM;
 #ifdef SIS_LINUX_KERNEL
 	unsigned char SISIOMEMTYPE	*VideoMemoryAddress;
 	unsigned int			VideoMemorySize;
@@ -283,24 +283,24 @@
 #ifdef SIS_XORG_XF86
 	unsigned short			SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
 #endif
-	BOOLEAN				SiS_UseROM;
-	BOOLEAN				SiS_ROMNew;
-	BOOLEAN				SiS_XGIROM;
-	BOOLEAN				SiS_NeedRomModeData;
-	BOOLEAN				PanelSelfDetected;
-	BOOLEAN				DDCPortMixup;
+	bool				SiS_UseROM;
+	bool				SiS_ROMNew;
+	bool				SiS_XGIROM;
+	bool				SiS_NeedRomModeData;
+	bool				PanelSelfDetected;
+	bool				DDCPortMixup;
 	int				SiS_CHOverScan;
-	BOOLEAN				SiS_CHSOverScan;
-	BOOLEAN				SiS_ChSW;
-	BOOLEAN				SiS_UseLCDA;
+	bool				SiS_CHSOverScan;
+	bool				SiS_ChSW;
+	bool				SiS_UseLCDA;
 	int				SiS_UseOEM;
 	unsigned int			SiS_CustomT;
 	int				SiS_UseWide, SiS_UseWideCRT2;
 	int				SiS_TVBlue;
 	unsigned short			SiS_Backup70xx;
-	BOOLEAN				HaveEMI;
-	BOOLEAN				HaveEMILCD;
-	BOOLEAN				OverruleEMI;
+	bool				HaveEMI;
+	bool				HaveEMILCD;
+	bool				OverruleEMI;
 	unsigned char			EMI_30,EMI_31,EMI_32,EMI_33;
 	unsigned short			SiS_EMIOffset;
 	unsigned short			SiS_PWDOffset;
@@ -352,7 +352,7 @@
 	unsigned short			SiS_DDC_ReadAddr;
 	unsigned short			SiS_DDC_SecAddr;
 	unsigned short			SiS_ChrontelInit;
-	BOOLEAN				SiS_SensibleSR11;
+	bool				SiS_SensibleSR11;
 	unsigned short			SiS661LCD2TableSize;
 
 	unsigned short			SiS_PanelMinLVDS;
@@ -494,10 +494,10 @@
 	unsigned short			PanelVRS,  PanelVRE;
 	unsigned short			PanelVCLKIdx300;
 	unsigned short			PanelVCLKIdx315;
-	BOOLEAN				Alternate1600x1200;
+	bool				Alternate1600x1200;
 
-	BOOLEAN				UseCustomMode;
-	BOOLEAN				CRT1UsesCustomMode;
+	bool				UseCustomMode;
+	bool				CRT1UsesCustomMode;
 	unsigned short			CHDisplay;
 	unsigned short			CHSyncStart;
 	unsigned short			CHSyncEnd;
@@ -523,7 +523,7 @@
 
 	int				LVDSHL;
 
-	BOOLEAN				Backup;
+	bool				Backup;
 	unsigned char			Backup_Mode;
 	unsigned char			Backup_14;
 	unsigned char			Backup_15;
@@ -542,12 +542,12 @@
 	int				CenterScreen;
 
 	unsigned short			CP_Vendor, CP_Product;
-	BOOLEAN				CP_HaveCustomData;
+	bool				CP_HaveCustomData;
 	int				CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
 	int				CP_MaxX, CP_MaxY, CP_MaxClock;
 	unsigned char			CP_PrefSR2B, CP_PrefSR2C;
 	unsigned short			CP_PrefClock;
-	BOOLEAN				CP_Supports64048075;
+	bool				CP_Supports64048075;
 	int				CP_HDisplay[7], CP_VDisplay[7];	/* For Custom LCD panel dimensions */
 	int				CP_HTotal[7], CP_VTotal[7];
 	int				CP_HSyncStart[7], CP_VSyncStart[7];
@@ -555,8 +555,8 @@
 	int				CP_HBlankStart[7], CP_VBlankStart[7];
 	int				CP_HBlankEnd[7], CP_VBlankEnd[7];
 	int				CP_Clock[7];
-	BOOLEAN				CP_DataValid[7];
-	BOOLEAN				CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
+	bool				CP_DataValid[7];
+	bool				CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
 };
 
 #endif
diff --git a/drivers/video/sun3fb.c b/drivers/video/sun3fb.c
deleted file mode 100644
index f80356d..0000000
--- a/drivers/video/sun3fb.c
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- *  linux/drivers/video/sun3fb.c -- Frame buffer driver for Sun3
- *
- * (C) 1998 Thomas Bogendoerfer
- *
- * This driver is bases on sbusfb.c, which is
- *
- *	Copyright (C) 1998 Jakub Jelinek
- *
- *  This driver is partly based on the Open Firmware console driver
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  and SPARC console subsystem
- *
- *      Copyright (C) 1995 Peter Zaitcev (zaitcev@yahoo.com)
- *      Copyright (C) 1995-1997 David S. Miller (davem@caip.rutgers.edu)
- *      Copyright (C) 1995-1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
- *      Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
- *      Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *      Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/selection.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>	/* io_remap_page_range() */
-
-#ifdef CONFIG_SUN3
-#include <asm/oplib.h>
-#include <asm/machines.h>
-#include <asm/idprom.h>
-
-#define CGFOUR_OBMEM_ADDR 0x1f300000
-#define BWTWO_OBMEM_ADDR 0x1f000000
-#define BWTWO_OBMEM50_ADDR 0x00100000
-
-#endif
-#ifdef CONFIG_SUN3X
-#include <asm/sun3x.h>
-#endif
-#include <video/sbusfb.h>
-
-#define DEFAULT_CURSOR_BLINK_RATE       (2*HZ/5)
-
-#define CURSOR_SHAPE			1
-#define CURSOR_BLINK			2
-
-#define mymemset(x,y) memset(x,0,y)
-
-    /*
-     *  Interface used by the world
-     */
-
-int sun3fb_init(void);
-void sun3fb_setup(char *options);
-
-static char fontname[40] __initdata = { 0 };
-static int curblink __initdata = 1;
-
-static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			struct fb_info *info);
-static int sun3fb_get_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info);
-static int sun3fb_set_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info);
-static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			struct fb_info *info);
-static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			struct fb_info *info);
-static int sun3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			    u_int transp, struct fb_info *info);
-static int sun3fb_blank(int blank, struct fb_info *info);
-static void sun3fb_cursor(struct display *p, int mode, int x, int y);
-static void sun3fb_clear_margin(struct display *p, int s);
-
-    /*
-     *  Interface to the low level console driver
-     */
-
-static int sun3fbcon_switch(int con, struct fb_info *info);
-static int sun3fbcon_updatevar(int con, struct fb_info *info);
-
-    /*
-     *  Internal routines
-     */
-
-static int sun3fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			    u_int *transp, struct fb_info *info);
-
-static struct fb_ops sun3fb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	sun3fb_get_fix,
-	.fb_get_var =	sun3fb_get_var,
-	.fb_set_var =	sun3fb_set_var,
-	.fb_get_cmap =	sun3fb_get_cmap,
-	.fb_set_cmap =	sun3fb_set_cmap,
-	.fb_setcolreg =	sun3fb_setcolreg,
-	.fb_blank =	sun3fb_blank,
-};
-
-static void sun3fb_clear_margin(struct display *p, int s)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-	
-	return;
-
-	if (fb->switch_from_graph)
-		(*fb->switch_from_graph)(fb);
-	if (fb->fill) {
-		unsigned short rects [16];
-
-		rects [0] = 0;
-		rects [1] = 0;
-		rects [2] = fb->var.xres_virtual;
-		rects [3] = fb->y_margin;
-		rects [4] = 0;
-		rects [5] = fb->y_margin;
-		rects [6] = fb->x_margin;
-		rects [7] = fb->var.yres_virtual;
-		rects [8] = fb->var.xres_virtual - fb->x_margin;
-		rects [9] = fb->y_margin;
-		rects [10] = fb->var.xres_virtual;
-		rects [11] = fb->var.yres_virtual;
-		rects [12] = fb->x_margin;
-		rects [13] = fb->var.yres_virtual - fb->y_margin;
-		rects [14] = fb->var.xres_virtual - fb->x_margin;
-		rects [15] = fb->var.yres_virtual;
-		(*fb->fill)(fb, p, s, 4, rects);
-	} else {
-		unsigned char *fb_base = fb->info.screen_base, *q;
-		int skip_bytes = fb->y_margin * fb->var.xres_virtual;
-		int scr_size = fb->var.xres_virtual * fb->var.yres_virtual;
-		int h, he, incr, size;
-
-		he = fb->var.yres;
-		if (fb->var.bits_per_pixel == 1) {
-			fb_base -= (skip_bytes + fb->x_margin) / 8;
-			skip_bytes /= 8;
-			scr_size /= 8;
-			mymemset (fb_base, skip_bytes - fb->x_margin / 8);
-			mymemset (fb_base + scr_size - skip_bytes + fb->x_margin / 8, skip_bytes - fb->x_margin / 8);
-			incr = fb->var.xres_virtual / 8;
-			size = fb->x_margin / 8 * 2;
-			for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0;
-			     h <= he; q += incr, h++)
-				mymemset (q, size);
-		} else {
-			fb_base -= (skip_bytes + fb->x_margin);
-			memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin);
-			memset (fb_base + scr_size - skip_bytes + fb->x_margin, attr_bgcol(p,s), skip_bytes - fb->x_margin);
-			incr = fb->var.xres_virtual;
-			size = fb->x_margin * 2;
-			for (q = fb_base + skip_bytes - fb->x_margin, h = 0;
-			     h <= he; q += incr, h++)
-				memset (q, attr_bgcol(p,s), size);
-		}
-	}
-}
-
-static void sun3fb_disp_setup(struct display *p)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-
-	if (fb->setup)
-		fb->setup(p);	
-	sun3fb_clear_margin(p, 0);
-}
-
-    /*
-     *  Get the Fixed Part of the Display
-     */
-
-static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			  struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo));
-	return 0;
-}
-
-    /*
-     *  Get the User Defined Part of the Display
-     */
-
-static int sun3fb_get_var(struct fb_var_screeninfo *var, int con,
-			  struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
-	return 0;
-}
-
-    /*
-     *  Set the User Defined Part of the Display
-     */
-
-static int sun3fb_set_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	if (var->xres > fb->var.xres || var->yres > fb->var.yres ||
-	    var->xres_virtual > fb->var.xres_virtual ||
-	    var->yres_virtual > fb->var.yres_virtual ||
-	    var->bits_per_pixel != fb->var.bits_per_pixel ||
-	    var->nonstd ||
-	    (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		return -EINVAL;
-	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));
-	return 0;
-}
-
-    /*
-     *  Hardware cursor
-     */
-     
-static unsigned char hw_cursor_cmap[2] = { 0, 0xff };
-
-static void
-sun3fb_cursor_timer_handler(unsigned long dev_addr)
-{
-	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)dev_addr;
-        
-	if (!fb->setcursor) return;
-                                
-	if (fb->cursor.mode & CURSOR_BLINK) {
-		fb->cursor.enable ^= 1;
-		fb->setcursor(fb);
-	}
-	
-	fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
-	add_timer(&fb->cursor.timer);
-}
-
-static void sun3fb_cursor(struct display *p, int mode, int x, int y)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-	
-	switch (mode) {
-	case CM_ERASE:
-		fb->cursor.mode &= ~CURSOR_BLINK;
-		fb->cursor.enable = 0;
-		(*fb->setcursor)(fb);
-		break;
-				  
-	case CM_MOVE:
-	case CM_DRAW:
-		if (fb->cursor.mode & CURSOR_SHAPE) {
-			fb->cursor.size.fbx = fontwidth(p);
-			fb->cursor.size.fby = fontheight(p);
-			fb->cursor.chot.fbx = 0;
-			fb->cursor.chot.fby = 0;
-			fb->cursor.enable = 1;
-			memset (fb->cursor.bits, 0, sizeof (fb->cursor.bits));
-			fb->cursor.bits[0][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
-			fb->cursor.bits[1][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
-			fb->cursor.bits[0][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
-			fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
-			(*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap);
-			(*fb->setcurshape) (fb);
-		}
-		fb->cursor.mode = CURSOR_BLINK;
-		if (fontwidthlog(p))
-			fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin;
-		else
-			fb->cursor.cpos.fbx = (x * fontwidth(p)) + fb->x_margin;
-		if (fontheightlog(p))
-			fb->cursor.cpos.fby = (y << fontheightlog(p)) + fb->y_margin;
-		else
-			fb->cursor.cpos.fby = (y * fontheight(p)) + fb->y_margin;
-		(*fb->setcursor)(fb);
-		break;
-	}
-}
-
-    /*
-     *  Get the Colormap
-     */
-
-static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			 struct fb_info *info)
-{
-	if (con == info->currcon) /* current console? */
-		return fb_get_cmap(cmap, kspc, sun3fb_getcolreg, info);
-	else if (fb_display[con].cmap.len) /* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2);
-	return 0;
-}
-
-    /*
-     *  Set the Colormap
-     */
-
-static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			 struct fb_info *info)
-{
-	int err;
-
-	if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
-		if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0)))
-			return err;
-	}
-	if (con == info->currcon) {			/* current console? */
-		err = fb_set_cmap(cmap, kspc, info);
-		if (!err) {
-			struct fb_info_sbusfb *fb = sbusfbinfo(info);
-			
-			if (fb->loadcmap)
-				(*fb->loadcmap)(fb, &fb_display[con], cmap->start, cmap->len);
-		}
-		return err;
-	} else
-		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-	return 0;
-}
-
-    /*
-     *  Setup: parse used options
-     */
-
-void __init sun3fb_setup(char *options)
-{
-	char *p;
-	
-	for (p = options;;) {
-		if (!strncmp(p, "font=", 5)) {
-			int i;
-			
-			for (i = 0; i < sizeof(fontname) - 1; i++)
-				if (p[i+5] == ' ' || !p[i+5])
-					break;
-			memcpy(fontname, p+5, i);
-			fontname[i] = 0;
-		} else if (!strncmp(p, "noblink", 7))
-			curblink = 0;
-		while (*p && *p != ' ' && *p != ',') p++;
-		if (*p != ',') break;
-		p++;
-	}
-
-	return;
-}
-
-static int sun3fbcon_switch(int con, struct fb_info *info)
-{
-	int x_margin, y_margin;
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-	int lastconsole;
-    
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len)
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1, sun3fb_getcolreg, info);
-
-	if (info->display_fg) {
-		lastconsole = info->display_fg->vc_num;
-		if (lastconsole != con && 
-		    (fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) ||
-		     fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con])))
-			fb->cursor.mode |= CURSOR_SHAPE;
-	}
-	x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2;
-	y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2;
-	if (fb->margins)
-		fb->margins(fb, &fb_display[con], x_margin, y_margin);
-	if (fb->graphmode || fb->x_margin != x_margin || fb->y_margin != y_margin) {
-		fb->x_margin = x_margin; fb->y_margin = y_margin;
-		sun3fb_clear_margin(&fb_display[con], 0);
-	}
-	info->currcon = con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	return 0;
-}
-
-    /*
-     *  Update the `var' structure (called by fbcon.c)
-     */
-
-static int sun3fbcon_updatevar(int con, struct fb_info *info)
-{
-	/* Nothing */
-	return 0;
-}
-
-    /*
-     *  Blank the display.
-     */
-
-static int sun3fb_blank(int blank, struct fb_info *info)
-{
-    struct fb_info_sbusfb *fb = sbusfbinfo(info);
-    
-    if (blank && fb->blank)
-    	return fb->blank(fb);
-    else if (!blank && fb->unblank)
-    	return fb->unblank(fb);
-    return 0;
-}
-
-    /*
-     *  Read a single color register and split it into
-     *  colors/transparent. Return != 0 for invalid regno.
-     */
-
-static int sun3fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			  u_int *transp, struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	if (!fb->color_map || regno > 255)
-		return 1;
-	*red = (fb->color_map CM(regno, 0)<<8) | fb->color_map CM(regno, 0);
-	*green = (fb->color_map CM(regno, 1)<<8) | fb->color_map CM(regno, 1);
-	*blue = (fb->color_map CM(regno, 2)<<8) | fb->color_map CM(regno, 2);
-	*transp = 0;
-	return 0;
-}
-
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int sun3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			    u_int transp, struct fb_info *info)
-{
-	struct fb_info_sbusfb *fb = sbusfbinfo(info);
-
-	if (!fb->color_map || regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	fb->color_map CM(regno, 0) = red;
-	fb->color_map CM(regno, 1) = green;
-	fb->color_map CM(regno, 2) = blue;
-	return 0;
-}
-
-static int sun3fb_set_font(struct display *p, int width, int height)
-{
-	int w = p->var.xres_virtual, h = p->var.yres_virtual;
-	int depth = p->var.bits_per_pixel;
-	struct fb_info_sbusfb *fb = sbusfbinfod(p);
-	int x_margin, y_margin;
-	
-	if (depth > 8) depth = 8;
-	x_margin = (w % width) / 2;
-	y_margin = (h % height) / 2;
-
-	p->var.xres = w - 2*x_margin;
-	p->var.yres = h - 2*y_margin;
-	
-	fb->cursor.mode |= CURSOR_SHAPE;
-	
-	if (fb->margins)
-		fb->margins(fb, p, x_margin, y_margin);
-	if (fb->x_margin != x_margin || fb->y_margin != y_margin) {
-		fb->x_margin = x_margin; fb->y_margin = y_margin;
-		sun3fb_clear_margin(p, 0);
-	}
-
-	return 1;
-}
-
-void sun3fb_palette(int enter)
-{
-	int i;
-	struct display *p;
-	
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
-		p = &fb_display[i];
-		if (p->dispsw && p->dispsw->setup == sun3fb_disp_setup &&
-		    p->fb_info->display_fg &&
-		    p->fb_info->display_fg->vc_num == i) {
-			struct fb_info_sbusfb *fb = sbusfbinfod(p);
-
-			if (fb->restore_palette) {
-				if (enter)
-					fb->restore_palette(fb);
-				else if (vc_cons[i].d->vc_mode != KD_GRAPHICS)
-				         vc_cons[i].d->vc_sw->con_set_palette(vc_cons[i].d, color_table);
-			}
-		}
-	}
-}
-
-    /*
-     *  Initialisation
-     */
-static int __init sun3fb_init_fb(int fbtype, unsigned long addr)
-{
-	static struct sbus_dev sdb;
-	struct fb_fix_screeninfo *fix;
-	struct fb_var_screeninfo *var;
-	struct display *disp;
-	struct fb_info_sbusfb *fb;
-	struct fbtype *type;
-	int linebytes, w, h, depth;
-	char *p = NULL;
-	
-	fb = kmalloc(sizeof(struct fb_info_sbusfb), GFP_ATOMIC);
-	if (!fb)
-		return -ENOMEM;
-	
-	memset(fb, 0, sizeof(struct fb_info_sbusfb));
-	fix = &fb->fix;
-	var = &fb->var;
-	disp = &fb->disp;
-	type = &fb->type;
-	
-	sdb.reg_addrs[0].phys_addr = addr;
-	fb->sbdp = &sdb;
-
-	type->fb_type = fbtype;
-	
-	type->fb_height = h = 900;
-	type->fb_width  = w = 1152;
-sizechange:
-	type->fb_depth  = depth = (fbtype == FBTYPE_SUN2BW) ? 1 : 8;
-	linebytes = w * depth / 8;
-	type->fb_size   = PAGE_ALIGN((linebytes) * h);
-/*	
-	fb->x_margin = (w & 7) / 2;
-	fb->y_margin = (h & 15) / 2;
-*/
-	fb->x_margin = fb->y_margin = 0;
-
-	var->xres_virtual = w;
-	var->yres_virtual = h;
-	var->xres = w - 2*fb->x_margin;
-	var->yres = h - 2*fb->y_margin;
-	
-	var->bits_per_pixel = depth;
-	var->height = var->width = -1;
-	var->pixclock = 10000;
-	var->vmode = FB_VMODE_NONINTERLACED;
-	var->red.length = var->green.length = var->blue.length = 8;
-
-	fix->line_length = linebytes;
-	fix->smem_len = type->fb_size;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	
-	fb->info.fbops = &sun3fb_ops;
-	fb->info.disp = disp;
-	fb->info.currcon = -1;
-	strcpy(fb->info.fontname, fontname);
-	fb->info.changevar = NULL;
-	fb->info.switch_con = &sun3fbcon_switch;
-	fb->info.updatevar = &sun3fbcon_updatevar;
-	fb->info.flags = FBINFO_FLAG_DEFAULT;
-	
-	fb->cursor.hwsize.fbx = 32;
-	fb->cursor.hwsize.fby = 32;
-	
-	if (depth > 1 && !fb->color_map) {
-		if((fb->color_map = kmalloc(256 * 3, GFP_ATOMIC))==NULL)
-			return -ENOMEM;
-	}
-			
-	switch(fbtype) {
-#ifdef CONFIG_FB_CGSIX
-	case FBTYPE_SUNFAST_COLOR:
-		p = cgsixfb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_BWTWO
-	case FBTYPE_SUN2BW:
-		p = bwtwofb_init(fb); break;
-#endif
-#ifdef CONFIG_FB_CGTHREE
-	case FBTYPE_SUN4COLOR:
-	case FBTYPE_SUN3COLOR:
-		type->fb_size = 0x100000;
-		p = cgthreefb_init(fb); break;
-#endif
-	}
-	fix->smem_start = (unsigned long)fb->info.screen_base;	// FIXME
-	
-	if (!p) {
-		kfree(fb);
-		return -ENODEV;
-	}
-	
-	if (p == SBUSFBINIT_SIZECHANGE)
-		goto sizechange;
-
-	disp->dispsw = &fb->dispsw;
-	if (fb->setcursor) {
-		fb->dispsw.cursor = sun3fb_cursor;
-		if (curblink) {
-			fb->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
-			init_timer(&fb->cursor.timer);
-			fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
-			fb->cursor.timer.data = (unsigned long)fb;
-			fb->cursor.timer.function = sun3fb_cursor_timer_handler;
-			add_timer(&fb->cursor.timer);
-		}
-	}
-	fb->cursor.mode = CURSOR_SHAPE;
-	fb->dispsw.set_font = sun3fb_set_font;
-	fb->setup = fb->dispsw.setup;
-	fb->dispsw.setup = sun3fb_disp_setup;
-	fb->dispsw.clear_margins = NULL;
-
-	disp->var = *var;
-	disp->visual = fix->visual;
-	disp->type = fix->type;
-	disp->type_aux = fix->type_aux;
-	disp->line_length = fix->line_length;
-	
-	if (fb->blank)
-		disp->can_soft_blank = 1;
-
-	sun3fb_set_var(var, -1, &fb->info);
-
-	if (register_framebuffer(&fb->info) < 0) {
-		kfree(fb);
-		return -EINVAL;
-	}
-	printk("fb%d: %s\n", fb->info.node, p);
-
-	return 0;
-}
-
-
-int __init sun3fb_init(void)
-{
-	extern int con_is_present(void);
-	unsigned long addr;
-	char p4id;
-	
-	if (!con_is_present()) return -ENODEV;
-#ifdef CONFIG_SUN3
-        switch(*(romvec->pv_fbtype))
-        {
-	case FBTYPE_SUN2BW:
-		addr = 0xfe20000;
-		return sun3fb_init_fb(FBTYPE_SUN2BW, addr);
-	case FBTYPE_SUN3COLOR:
-	case FBTYPE_SUN4COLOR:
-		if(idprom->id_machtype != (SM_SUN3|SM_3_60)) {
-			printk("sun3fb: cgthree/four only supported on 3/60\n");
-			return -ENODEV;
-		}
-		
-		addr = CGFOUR_OBMEM_ADDR;
-		return sun3fb_init_fb(*(romvec->pv_fbtype), addr);
-	default:
-		printk("sun3fb: unsupported framebuffer\n");
-		return -ENODEV;
-	}
-#else
-	addr = SUN3X_VIDEO_BASE;
-	p4id = *(char *)SUN3X_VIDEO_P4ID;
-
-	p4id = (p4id == 0x45) ? p4id : (p4id & 0xf0);
-	switch (p4id) {
-		case 0x00:
-			return sun3fb_init_fb(FBTYPE_SUN2BW, addr);
-#if 0 /* not yet */
-		case 0x40:
-			return sun3fb_init_fb(FBTYPE_SUN4COLOR, addr);
-			break;
-		case 0x45:
-			return sun3fb_init_fb(FBTYPE_SUN8COLOR, addr);
-			break;
-#endif
-		case 0x60:
-			return sun3fb_init_fb(FBTYPE_SUNFAST_COLOR, addr);
-	}
-#endif			
-	
-	return -ENODEV;
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/svgalib.c b/drivers/video/svgalib.c
new file mode 100644
index 0000000..68b30d9
--- /dev/null
+++ b/drivers/video/svgalib.c
@@ -0,0 +1,632 @@
+/*
+ * Common utility functions for VGA-based graphics cards.
+ *
+ * Copyright (c) 2006-2007 Ondrej Zajicek <santiago@crfreenet.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Some parts are based on David Boucher's viafb (http://davesdomain.org.uk/viafb/)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/svga.h>
+#include <linux/slab.h>
+#include <asm/types.h>
+#include <asm/io.h>
+
+
+/* Write a CRT register value spread across multiple registers */
+void svga_wcrt_multi(const struct vga_regset *regset, u32 value) {
+
+	u8 regval, bitval, bitnum;
+
+	while (regset->regnum != VGA_REGSET_END_VAL) {
+		regval = vga_rcrt(NULL, regset->regnum);
+		bitnum = regset->lowbit;
+		while (bitnum <= regset->highbit) {
+			bitval = 1 << bitnum;
+			regval = regval & ~bitval;
+			if (value & 1) regval = regval | bitval;
+			bitnum ++;
+			value = value >> 1;
+		}
+		vga_wcrt(NULL, regset->regnum, regval);
+		regset ++;
+	}
+}
+
+/* Write a sequencer register value spread across multiple registers */
+void svga_wseq_multi(const struct vga_regset *regset, u32 value) {
+
+	u8 regval, bitval, bitnum;
+
+	while (regset->regnum != VGA_REGSET_END_VAL) {
+		regval = vga_rseq(NULL, regset->regnum);
+		bitnum = regset->lowbit;
+		while (bitnum <= regset->highbit) {
+			bitval = 1 << bitnum;
+			regval = regval & ~bitval;
+			if (value & 1) regval = regval | bitval;
+			bitnum ++;
+			value = value >> 1;
+		}
+		vga_wseq(NULL, regset->regnum, regval);
+		regset ++;
+	}
+}
+
+static unsigned int svga_regset_size(const struct vga_regset *regset)
+{
+	u8 count = 0;
+
+	while (regset->regnum != VGA_REGSET_END_VAL) {
+		count += regset->highbit - regset->lowbit + 1;
+		regset ++;
+	}
+	return 1 << count;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Set graphics controller registers to sane values */
+void svga_set_default_gfx_regs(void)
+{
+	/* All standard GFX registers (GR00 - GR08) */
+	vga_wgfx(NULL, VGA_GFX_SR_VALUE, 0x00);
+	vga_wgfx(NULL, VGA_GFX_SR_ENABLE, 0x00);
+	vga_wgfx(NULL, VGA_GFX_COMPARE_VALUE, 0x00);
+	vga_wgfx(NULL, VGA_GFX_DATA_ROTATE, 0x00);
+	vga_wgfx(NULL, VGA_GFX_PLANE_READ, 0x00);
+	vga_wgfx(NULL, VGA_GFX_MODE, 0x00);
+/*	vga_wgfx(NULL, VGA_GFX_MODE, 0x20); */
+/*	vga_wgfx(NULL, VGA_GFX_MODE, 0x40); */
+	vga_wgfx(NULL, VGA_GFX_MISC, 0x05);
+/*	vga_wgfx(NULL, VGA_GFX_MISC, 0x01); */
+	vga_wgfx(NULL, VGA_GFX_COMPARE_MASK, 0x0F);
+	vga_wgfx(NULL, VGA_GFX_BIT_MASK, 0xFF);
+}
+
+/* Set attribute controller registers to sane values */
+void svga_set_default_atc_regs(void)
+{
+	u8 count;
+
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x00);
+
+	/* All standard ATC registers (AR00 - AR14) */
+	for (count = 0; count <= 0xF; count ++)
+		svga_wattr(count, count);
+
+	svga_wattr(VGA_ATC_MODE, 0x01);
+/*	svga_wattr(VGA_ATC_MODE, 0x41); */
+	svga_wattr(VGA_ATC_OVERSCAN, 0x00);
+	svga_wattr(VGA_ATC_PLANE_ENABLE, 0x0F);
+	svga_wattr(VGA_ATC_PEL, 0x00);
+	svga_wattr(VGA_ATC_COLOR_PAGE, 0x00);
+
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x20);
+}
+
+/* Set sequencer registers to sane values */
+void svga_set_default_seq_regs(void)
+{
+	/* Standard sequencer registers (SR01 - SR04), SR00 is not set */
+	vga_wseq(NULL, VGA_SEQ_CLOCK_MODE, VGA_SR01_CHAR_CLK_8DOTS);
+	vga_wseq(NULL, VGA_SEQ_PLANE_WRITE, VGA_SR02_ALL_PLANES);
+	vga_wseq(NULL, VGA_SEQ_CHARACTER_MAP, 0x00);
+/*	vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE | VGA_SR04_CHN_4M); */
+	vga_wseq(NULL, VGA_SEQ_MEMORY_MODE, VGA_SR04_EXT_MEM | VGA_SR04_SEQ_MODE);
+}
+
+/* Set CRTC registers to sane values */
+void svga_set_default_crt_regs(void)
+{
+	/* Standard CRT registers CR03 CR08 CR09 CR14 CR17 */
+	svga_wcrt_mask(0x03, 0x80, 0x80);	/* Enable vertical retrace EVRA */
+	vga_wcrt(NULL, VGA_CRTC_PRESET_ROW, 0);
+	svga_wcrt_mask(VGA_CRTC_MAX_SCAN, 0, 0x1F);
+	vga_wcrt(NULL, VGA_CRTC_UNDERLINE, 0);
+	vga_wcrt(NULL, VGA_CRTC_MODE, 0xE3);
+}
+
+void svga_set_textmode_vga_regs(void)
+{
+	/* svga_wseq_mask(0x1, 0x00, 0x01); */   /* Switch 8/9 pixel per char */
+	vga_wseq(NULL, VGA_SEQ_MEMORY_MODE,	VGA_SR04_EXT_MEM);
+	vga_wseq(NULL, VGA_SEQ_PLANE_WRITE,	0x03);
+
+	vga_wcrt(NULL, VGA_CRTC_MAX_SCAN,	0x0f); /* 0x4f */
+	vga_wcrt(NULL, VGA_CRTC_UNDERLINE,	0x1f);
+	svga_wcrt_mask(VGA_CRTC_MODE,		0x23, 0x7f);
+
+	vga_wcrt(NULL, VGA_CRTC_CURSOR_START,	0x0d);
+	vga_wcrt(NULL, VGA_CRTC_CURSOR_END,	0x0e);
+	vga_wcrt(NULL, VGA_CRTC_CURSOR_HI,	0x00);
+	vga_wcrt(NULL, VGA_CRTC_CURSOR_LO,	0x00);
+
+	vga_wgfx(NULL, VGA_GFX_MODE,		0x10); /* Odd/even memory mode */
+	vga_wgfx(NULL, VGA_GFX_MISC,		0x0E); /* Misc graphics register - text mode enable */
+	vga_wgfx(NULL, VGA_GFX_COMPARE_MASK,	0x00);
+
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x00);
+
+	svga_wattr(0x10, 0x0C);			/* Attribute Mode Control Register - text mode, blinking and line graphics */
+	svga_wattr(0x13, 0x08);			/* Horizontal Pixel Panning Register  */
+
+	vga_r(NULL, 0x3DA);
+	vga_w(NULL, VGA_ATT_W, 0x20);
+}
+
+#if 0
+void svga_dump_var(struct fb_var_screeninfo *var, int node)
+{
+	pr_debug("fb%d: var.vmode         : 0x%X\n", node, var->vmode);
+	pr_debug("fb%d: var.xres          : %d\n", node, var->xres);
+	pr_debug("fb%d: var.yres          : %d\n", node, var->yres);
+	pr_debug("fb%d: var.bits_per_pixel: %d\n", node, var->bits_per_pixel);
+	pr_debug("fb%d: var.xres_virtual  : %d\n", node, var->xres_virtual);
+	pr_debug("fb%d: var.yres_virtual  : %d\n", node, var->yres_virtual);
+	pr_debug("fb%d: var.left_margin   : %d\n", node, var->left_margin);
+	pr_debug("fb%d: var.right_margin  : %d\n", node, var->right_margin);
+	pr_debug("fb%d: var.upper_margin  : %d\n", node, var->upper_margin);
+	pr_debug("fb%d: var.lower_margin  : %d\n", node, var->lower_margin);
+	pr_debug("fb%d: var.hsync_len     : %d\n", node, var->hsync_len);
+	pr_debug("fb%d: var.vsync_len     : %d\n", node, var->vsync_len);
+	pr_debug("fb%d: var.sync          : 0x%X\n", node, var->sync);
+	pr_debug("fb%d: var.pixclock      : %d\n\n", node, var->pixclock);
+}
+#endif  /*  0  */
+
+
+/* ------------------------------------------------------------------------- */
+
+
+void svga_settile(struct fb_info *info, struct fb_tilemap *map)
+{
+	const u8 *font = map->data;
+	u8* fb = (u8 *) info->screen_base;
+	int i, c;
+
+	if ((map->width != 8) || (map->height != 16) ||
+	    (map->depth != 1) || (map->length != 256)) {
+	    	printk(KERN_ERR "fb%d: unsupported font parameters: width %d, height %d, depth %d, length %d\n",
+			info->node, map->width, map->height, map->depth, map->length);
+		return;
+	}
+
+	fb += 2;
+	for (c = 0; c < map->length; c++) {
+		for (i = 0; i < map->height; i++) {
+			fb[i * 4] = font[i];
+		}
+		fb += 128;
+		font += map->height;
+	}
+}
+
+/* Copy area in text (tileblit) mode */
+void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area)
+{
+	int dx, dy;
+	/*  colstride is halved in this function because u16 are used */
+	int colstride = 1 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	u16 *fb = (u16 *) info->screen_base;
+	u16 *src, *dst;
+
+	if ((area->sy > area->dy) ||
+	    ((area->sy == area->dy) && (area->sx > area->dx))) {
+		src = fb + area->sx * colstride + area->sy * rowstride;
+		dst = fb + area->dx * colstride + area->dy * rowstride;
+	    } else {
+		src = fb + (area->sx + area->width - 1) * colstride
+			 + (area->sy + area->height - 1) * rowstride;
+		dst = fb + (area->dx + area->width - 1) * colstride
+			 + (area->dy + area->height - 1) * rowstride;
+
+		colstride = -colstride;
+		rowstride = -rowstride;
+	    }
+
+	for (dy = 0; dy < area->height; dy++) {
+		u16* src2 = src;
+		u16* dst2 = dst;
+		for (dx = 0; dx < area->width; dx++) {
+			*dst2 = *src2;
+			src2 += colstride;
+			dst2 += colstride;
+		}
+		src += rowstride;
+		dst += rowstride;
+	}
+}
+
+/* Fill area in text (tileblit) mode */
+void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect)
+{
+	int dx, dy;
+	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	int attr = (0x0F & rect->bg) << 4 | (0x0F & rect->fg);
+	u8  *fb = (u8 *) info->screen_base;
+	fb += rect->sx * colstride + rect->sy * rowstride;
+
+	for (dy = 0; dy < rect->height; dy++) {
+		u8* fb2 = fb;
+		for (dx = 0; dx < rect->width; dx++) {
+			fb2[0] = rect->index;
+			fb2[1] = attr;
+			fb2 += colstride;
+		}
+		fb += rowstride;
+	}
+}
+
+/* Write text in text (tileblit) mode */
+void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit)
+{
+	int dx, dy, i;
+	int colstride = 2 << (info->fix.type_aux & FB_AUX_TEXT_SVGA_MASK);
+	int rowstride = colstride * (info->var.xres_virtual / 8);
+	int attr = (0x0F & blit->bg) << 4 | (0x0F & blit->fg);
+	u8* fb = (u8 *) info->screen_base;
+	fb += blit->sx * colstride + blit->sy * rowstride;
+
+	i=0;
+	for (dy=0; dy < blit->height; dy ++) {
+		u8* fb2 = fb;
+		for (dx = 0; dx < blit->width; dx ++) {
+			fb2[0] = blit->indices[i];
+			fb2[1] = attr;
+			fb2 += colstride;
+			i ++;
+			if (i == blit->length) return;
+		}
+		fb += rowstride;
+	}
+
+}
+
+/* Set cursor in text (tileblit) mode */
+void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor)
+{
+	u8 cs = 0x0d;
+	u8 ce = 0x0e;
+	u16 pos =  cursor->sx + (info->var.xoffset /  8)
+		+ (cursor->sy + (info->var.yoffset / 16))
+		   * (info->var.xres_virtual / 8);
+
+	if (! cursor -> mode)
+		return;
+
+	svga_wcrt_mask(0x0A, 0x20, 0x20); /* disable cursor */
+
+	if (cursor -> shape == FB_TILE_CURSOR_NONE)
+		return;
+
+	switch (cursor -> shape) {
+	case FB_TILE_CURSOR_UNDERLINE:
+		cs = 0x0d;
+		break;
+	case FB_TILE_CURSOR_LOWER_THIRD:
+		cs = 0x09;
+		break;
+	case FB_TILE_CURSOR_LOWER_HALF:
+		cs = 0x07;
+		break;
+	case FB_TILE_CURSOR_TWO_THIRDS:
+		cs = 0x05;
+		break;
+	case FB_TILE_CURSOR_BLOCK:
+		cs = 0x01;
+		break;
+	}
+
+	/* set cursor position */
+	vga_wcrt(NULL, 0x0E, pos >> 8);
+	vga_wcrt(NULL, 0x0F, pos & 0xFF);
+
+	vga_wcrt(NULL, 0x0B, ce); /* set cursor end */
+	vga_wcrt(NULL, 0x0A, cs); /* set cursor start and enable it */
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/*
+ *  Compute PLL settings (M, N, R)
+ *  F_VCO = (F_BASE * M) / N
+ *  F_OUT = F_VCO / (2^R)
+ */
+
+static inline u32 abs_diff(u32 a, u32 b)
+{
+	return (a > b) ? (a - b) : (b - a);
+}
+
+int svga_compute_pll(const struct svga_pll *pll, u32 f_wanted, u16 *m, u16 *n, u16 *r, int node)
+{
+	u16 am, an, ar;
+	u32 f_vco, f_current, delta_current, delta_best;
+
+	pr_debug("fb%d: ideal frequency: %d kHz\n", node, (unsigned int) f_wanted);
+
+	ar = pll->r_max;
+	f_vco = f_wanted << ar;
+
+	/* overflow check */
+	if ((f_vco >> ar) != f_wanted)
+		return -EINVAL;
+
+	/* It is usually better to have greater VCO clock
+	   because of better frequency stability.
+	   So first try r_max, then r smaller. */
+	while ((ar > pll->r_min) && (f_vco > pll->f_vco_max)) {
+		ar--;
+		f_vco = f_vco >> 1;
+	}
+
+	/* VCO bounds check */
+	if ((f_vco < pll->f_vco_min) || (f_vco > pll->f_vco_max))
+		return -EINVAL;
+
+	delta_best = 0xFFFFFFFF;
+	*m = 0;
+	*n = 0;
+	*r = ar;
+
+	am = pll->m_min;
+	an = pll->n_min;
+
+	while ((am <= pll->m_max) && (an <= pll->n_max)) {
+		f_current = (pll->f_base * am) / an;
+		delta_current = abs_diff (f_current, f_vco);
+
+		if (delta_current < delta_best) {
+			delta_best = delta_current;
+			*m = am;
+			*n = an;
+		}
+
+		if (f_current <= f_vco) {
+			am ++;
+		} else {
+			an ++;
+		}
+	}
+
+	f_current = (pll->f_base * *m) / *n;
+	pr_debug("fb%d: found frequency: %d kHz (VCO %d kHz)\n", node, (int) (f_current >> ar), (int) f_current);
+	pr_debug("fb%d: m = %d n = %d r = %d\n", node, (unsigned int) *m, (unsigned int) *n, (unsigned int) *r);
+	return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/* Check CRT timing values */
+int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, int node)
+{
+	u32 value;
+
+	var->xres         = (var->xres+7)&~7;
+	var->left_margin  = (var->left_margin+7)&~7;
+	var->right_margin = (var->right_margin+7)&~7;
+	var->hsync_len    = (var->hsync_len+7)&~7;
+
+	/* Check horizontal total */
+	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+	if (((value / 8) - 5) >= svga_regset_size (tm->h_total_regs))
+		return -EINVAL;
+
+	/* Check horizontal display and blank start */
+	value = var->xres;
+	if (((value / 8) - 1) >= svga_regset_size (tm->h_display_regs))
+		return -EINVAL;
+	if (((value / 8) - 1) >= svga_regset_size (tm->h_blank_start_regs))
+		return -EINVAL;
+
+	/* Check horizontal sync start */
+	value = var->xres + var->right_margin;
+	if (((value / 8) - 1) >= svga_regset_size (tm->h_sync_start_regs))
+		return -EINVAL;
+
+	/* Check horizontal blank end (or length) */
+	value = var->left_margin + var->right_margin + var->hsync_len;
+	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_blank_end_regs)))
+		return -EINVAL;
+
+	/* Check horizontal sync end (or length) */
+	value = var->hsync_len;
+	if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_sync_end_regs)))
+		return -EINVAL;
+
+	/* Check vertical total */
+	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+	if ((value - 1) >= svga_regset_size(tm->v_total_regs))
+		return -EINVAL;
+
+	/* Check vertical display and blank start */
+	value = var->yres;
+	if ((value - 1) >= svga_regset_size(tm->v_display_regs))
+		return -EINVAL;
+	if ((value - 1) >= svga_regset_size(tm->v_blank_start_regs))
+		return -EINVAL;
+
+	/* Check vertical sync start */
+	value = var->yres + var->lower_margin;
+	if ((value - 1) >= svga_regset_size(tm->v_sync_start_regs))
+		return -EINVAL;
+
+	/* Check vertical blank end (or length) */
+	value = var->upper_margin + var->lower_margin + var->vsync_len;
+	if ((value == 0) || (value >= svga_regset_size (tm->v_blank_end_regs)))
+		return -EINVAL;
+
+	/* Check vertical sync end  (or length) */
+	value = var->vsync_len;
+	if ((value == 0) || (value >= svga_regset_size (tm->v_sync_end_regs)))
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Set CRT timing registers */
+void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var,
+			u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node)
+{
+	u8 regval;
+	u32 value;
+
+	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal total      : %d\n", node, value);
+	svga_wcrt_multi(tm->h_total_regs, (value / 8) - 5);
+
+	value = var->xres;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal display    : %d\n", node, value);
+	svga_wcrt_multi(tm->h_display_regs, (value / 8) - 1);
+
+	value = var->xres;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal blank start: %d\n", node, value);
+	svga_wcrt_multi(tm->h_blank_start_regs, (value / 8) - 1 + hborder);
+
+	value = var->xres + var->left_margin + var->right_margin + var->hsync_len;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal blank end  : %d\n", node, value);
+	svga_wcrt_multi(tm->h_blank_end_regs, (value / 8) - 1 - hborder);
+
+	value = var->xres + var->right_margin;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal sync start : %d\n", node, value);
+	svga_wcrt_multi(tm->h_sync_start_regs, (value / 8));
+
+	value = var->xres + var->right_margin + var->hsync_len;
+	value = (value * hmul) / hdiv;
+	pr_debug("fb%d: horizontal sync end   : %d\n", node, value);
+	svga_wcrt_multi(tm->h_sync_end_regs, (value / 8));
+
+	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical total        : %d\n", node, value);
+	svga_wcrt_multi(tm->v_total_regs, value - 2);
+
+	value = var->yres;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical display      : %d\n", node, value);
+	svga_wcrt_multi(tm->v_display_regs, value - 1);
+
+	value = var->yres;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical blank start  : %d\n", node, value);
+	svga_wcrt_multi(tm->v_blank_start_regs, value);
+
+	value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical blank end    : %d\n", node, value);
+	svga_wcrt_multi(tm->v_blank_end_regs, value - 2);
+
+	value = var->yres + var->lower_margin;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical sync start   : %d\n", node, value);
+	svga_wcrt_multi(tm->v_sync_start_regs, value);
+
+	value = var->yres + var->lower_margin + var->vsync_len;
+	value = (value * vmul) / vdiv;
+	pr_debug("fb%d: vertical sync end     : %d\n", node, value);
+	svga_wcrt_multi(tm->v_sync_end_regs, value);
+
+	/* Set horizontal and vertical sync pulse polarity in misc register */
+
+	regval = vga_r(NULL, VGA_MIS_R);
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT) {
+		pr_debug("fb%d: positive horizontal sync\n", node);
+		regval = regval & ~0x80;
+	} else {
+		pr_debug("fb%d: negative horizontal sync\n", node);
+		regval = regval | 0x80;
+	}
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT) {
+		pr_debug("fb%d: positive vertical sync\n", node);
+		regval = regval & ~0x40;
+	} else {
+		pr_debug("fb%d: negative vertical sync\n\n", node);
+		regval = regval | 0x40;
+	}
+	vga_w(NULL, VGA_MIS_W, regval);
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
+{
+	int i = 0;
+
+	while (frm->bits_per_pixel != SVGA_FORMAT_END_VAL)
+	{
+		if ((var->bits_per_pixel == frm->bits_per_pixel) &&
+		    (var->red.length     <= frm->red.length)     &&
+		    (var->green.length   <= frm->green.length)   &&
+		    (var->blue.length    <= frm->blue.length)    &&
+		    (var->transp.length  <= frm->transp.length)  &&
+		    (var->nonstd	 == frm->nonstd)) {
+		    	var->bits_per_pixel = frm->bits_per_pixel;
+			var->red            = frm->red;
+			var->green          = frm->green;
+			var->blue           = frm->blue;
+			var->transp         = frm->transp;
+			var->nonstd         = frm->nonstd;
+			if (fix != NULL) {
+				fix->type      = frm->type;
+				fix->type_aux  = frm->type_aux;
+				fix->visual    = frm->visual;
+				fix->xpanstep  = frm->xpanstep;
+			}
+			return i;
+		}
+		i++;
+		frm++;
+	}
+	return -EINVAL;
+}
+
+
+EXPORT_SYMBOL(svga_wcrt_multi);
+EXPORT_SYMBOL(svga_wseq_multi);
+
+EXPORT_SYMBOL(svga_set_default_gfx_regs);
+EXPORT_SYMBOL(svga_set_default_atc_regs);
+EXPORT_SYMBOL(svga_set_default_seq_regs);
+EXPORT_SYMBOL(svga_set_default_crt_regs);
+EXPORT_SYMBOL(svga_set_textmode_vga_regs);
+
+EXPORT_SYMBOL(svga_settile);
+EXPORT_SYMBOL(svga_tilecopy);
+EXPORT_SYMBOL(svga_tilefill);
+EXPORT_SYMBOL(svga_tileblit);
+EXPORT_SYMBOL(svga_tilecursor);
+
+EXPORT_SYMBOL(svga_compute_pll);
+EXPORT_SYMBOL(svga_check_timings);
+EXPORT_SYMBOL(svga_set_timings);
+EXPORT_SYMBOL(svga_match_format);
+
+MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>");
+MODULE_DESCRIPTION("Common utility functions for VGA-based graphics cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 4b88fab..b604859 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -43,8 +43,9 @@
 static void tgafb_fillrect(struct fb_info *, const struct fb_fillrect *);
 static void tgafb_copyarea(struct fb_info *, const struct fb_copyarea *);
 
-static int tgafb_pci_register(struct pci_dev *, const struct pci_device_id *);
-static void tgafb_pci_unregister(struct pci_dev *);
+static int __devinit tgafb_pci_register(struct pci_dev *,
+					const struct pci_device_id *);
+static void __devexit tgafb_pci_unregister(struct pci_dev *);
 
 static const char *mode_option = "640x480@60";
 
@@ -70,9 +71,10 @@
  */
 
 static struct pci_device_id const tgafb_pci_table[] = {
-	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, PCI_ANY_ID, PCI_ANY_ID,
-	  0, 0, 0 }
+	{ PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA) },
+	{ }
 };
+MODULE_DEVICE_TABLE(pci, tgafb_pci_table);
 
 static struct pci_driver tgafb_driver = {
 	.name			= "tgafb",
@@ -99,6 +101,12 @@
 		if (var->bits_per_pixel != 32)
 			return -EINVAL;
 	}
+	var->red.length = var->green.length = var->blue.length = 8;
+	if (var->bits_per_pixel == 32) {
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+	}
 
 	if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
 		return -EINVAL;
@@ -137,10 +145,10 @@
 		0x00000303
 	};
 	static unsigned int const mode_presets[4] = {
-		0x00002000,
-		0x00002300,
+		0x00000000,
+		0x00000300,
 		0xffffffff,
-		0x00002300
+		0x00000300
 	};
 	static unsigned int const base_addr_presets[4] = {
 		0x00000000,
@@ -152,7 +160,7 @@
 	struct tga_par *par = (struct tga_par *) info->par;
 	u32 htimings, vtimings, pll_freq;
 	u8 tga_type;
-	int i, j;
+	int i;
 
 	/* Encode video timings.  */
 	htimings = (((info->var.xres/4) & TGA_HORIZ_ACT_LSB)
@@ -190,7 +198,9 @@
 	while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
 		continue;
 	mb();
-	TGA_WRITE_REG(par, deep_presets[tga_type], TGA_DEEP_REG);
+	TGA_WRITE_REG(par, deep_presets[tga_type] |
+			   (par->sync_on_green ? 0x0 : 0x00010000),
+		      TGA_DEEP_REG);
 	while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
 		continue;
 	mb();
@@ -227,8 +237,10 @@
 		BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
 		TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
 
+#ifdef CONFIG_HW_CONSOLE
 		for (i = 0; i < 16; i++) {
-			j = color_table[i];
+			int j = color_table[i];
+
 			TGA_WRITE_REG(par, default_red[j]|(BT485_DATA_PAL<<8),
 				      TGA_RAMDAC_REG);
 			TGA_WRITE_REG(par, default_grn[j]|(BT485_DATA_PAL<<8),
@@ -236,24 +248,27 @@
 			TGA_WRITE_REG(par, default_blu[j]|(BT485_DATA_PAL<<8),
 				      TGA_RAMDAC_REG);
 		}
-		for (i = 0; i < 240*3; i += 4) {
-			TGA_WRITE_REG(par, 0x55|(BT485_DATA_PAL<<8),
+		for (i = 0; i < 240 * 3; i += 4) {
+#else
+		for (i = 0; i < 256 * 3; i += 4) {
+#endif
+			TGA_WRITE_REG(par, 0x55 | (BT485_DATA_PAL << 8),
 				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT485_DATA_PAL<<8),
+			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
 				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT485_DATA_PAL<<8),
+			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
 				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT485_DATA_PAL<<8),
+			TGA_WRITE_REG(par, 0x00 | (BT485_DATA_PAL << 8),
 				      TGA_RAMDAC_REG);
 		}
 
 	} else { /* 24-plane or 24plusZ */
 
-		/* Init BT463 registers.  */
+		/* Init BT463 RAMDAC registers.  */
 		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
 		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
 		BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_2,
-			    (par->sync_on_green ? 0x80 : 0x40));
+			    (par->sync_on_green ? 0xc0 : 0x40));
 
 		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
 		BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
@@ -267,26 +282,24 @@
 
 		/* Fill the palette.  */
 		BT463_LOAD_ADDR(par, 0x0000);
-		TGA_WRITE_REG(par, BT463_PALETTE<<2, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
 
+#ifdef CONFIG_HW_CONSOLE
 		for (i = 0; i < 16; i++) {
-			j = color_table[i];
-			TGA_WRITE_REG(par, default_red[j]|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, default_grn[j]|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, default_blu[j]|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
+			int j = color_table[i];
+
+			TGA_WRITE_REG(par, default_red[j], TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, default_grn[j], TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, default_blu[j], TGA_RAMDAC_REG);
 		}
-		for (i = 0; i < 512*3; i += 4) {
-			TGA_WRITE_REG(par, 0x55|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x00|(BT463_PALETTE<<10),
-				      TGA_RAMDAC_REG);
+		for (i = 0; i < 512 * 3; i += 4) {
+#else
+		for (i = 0; i < 528 * 3; i += 4) {
+#endif
+			TGA_WRITE_REG(par, 0x55, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
 		}
 
 		/* Fill window type table after start of vertical retrace.  */
@@ -299,15 +312,12 @@
 		TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
 
 		BT463_LOAD_ADDR(par, BT463_WINDOW_TYPE_BASE);
-		TGA_WRITE_REG(par, BT463_REG_ACC<<2, TGA_RAMDAC_SETUP_REG);
+		TGA_WRITE_REG(par, BT463_REG_ACC << 2, TGA_RAMDAC_SETUP_REG);
 
 		for (i = 0; i < 16; i++) {
-			TGA_WRITE_REG(par, 0x00|(BT463_REG_ACC<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x01|(BT463_REG_ACC<<10),
-				      TGA_RAMDAC_REG);
-			TGA_WRITE_REG(par, 0x80|(BT463_REG_ACC<<10),
-				      TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x01, TGA_RAMDAC_REG);
+			TGA_WRITE_REG(par, 0x00, TGA_RAMDAC_REG);
 		}
 
 	}
@@ -435,9 +445,16 @@
 		TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
 		TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
 		TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-	} else if (regno < 16) {
-		u32 value = (red << 16) | (green << 8) | blue;
-		((u32 *)info->pseudo_palette)[regno] = value;
+	} else {
+		if (regno < 16) {
+			u32 value = (regno << 16) | (regno << 8) | regno;
+			((u32 *)info->pseudo_palette)[regno] = value;
+		}
+		BT463_LOAD_ADDR(par, regno);
+		TGA_WRITE_REG(par, BT463_PALETTE << 2, TGA_RAMDAC_SETUP_REG);
+		TGA_WRITE_REG(par, red, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, green, TGA_RAMDAC_REG);
+		TGA_WRITE_REG(par, blue, TGA_RAMDAC_REG);
 	}
 
 	return 0;
@@ -885,7 +902,7 @@
 
 	n64 = (height * width) / 64;
 
-	if (dy < sy) {
+	if (sy < dy) {
 		spos = (sy + height) * width;
 		dpos = (dy + height) * width;
 
@@ -933,7 +950,7 @@
 
 	n16 = (height * width) / 16;
 
-	if (dy < sy) {
+	if (sy < dy) {
 		src = tga_fb + (sy + height) * width * 4;
 		dst = tga_fb + (dy + height) * width * 4;
 
@@ -1317,7 +1334,7 @@
 	info->fix.type_aux = 0;
 	info->fix.visual = (tga_type == TGA_TYPE_8PLANE
 			    ? FB_VISUAL_PSEUDOCOLOR
-			    : FB_VISUAL_TRUECOLOR);
+			    : FB_VISUAL_DIRECTCOLOR);
 
 	info->fix.line_length = par->xres * (par->bits_per_pixel >> 3);
 	info->fix.smem_start = (size_t) par->tga_fb_base;
@@ -1342,14 +1359,10 @@
 		TGA_24PLUSZ_FB_OFFSET
 	};
 
-	struct all_info {
-		struct fb_info info;
-		struct tga_par par;
-		u32 pseudo_palette[16];
-	} *all;
-
 	void __iomem *mem_base;
 	unsigned long bar0_start, bar0_len;
+	struct fb_info *info;
+	struct tga_par *par;
 	u8 tga_type;
 	int ret;
 
@@ -1360,13 +1373,14 @@
 	}
 
 	/* Allocate the fb and par structures.  */
-	all = kmalloc(sizeof(*all), GFP_KERNEL);
-	if (!all) {
+	info = framebuffer_alloc(sizeof(struct tga_par), &pdev->dev);
+	if (!info) {
 		printk(KERN_ERR "tgafb: Cannot allocate memory\n");
 		return -ENOMEM;
 	}
-	memset(all, 0, sizeof(*all));
-	pci_set_drvdata(pdev, all);
+
+	par = info->par;
+	pci_set_drvdata(pdev, info);
 
 	/* Request the mem regions.  */
 	bar0_start = pci_resource_start(pdev, 0);
@@ -1386,25 +1400,23 @@
 
 	/* Grab info about the card.  */
 	tga_type = (readl(mem_base) >> 12) & 0x0f;
-	all->par.pdev = pdev;
-	all->par.tga_mem_base = mem_base;
-	all->par.tga_fb_base = mem_base + fb_offset_presets[tga_type];
-	all->par.tga_regs_base = mem_base + TGA_REGS_OFFSET;
-	all->par.tga_type = tga_type;
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &all->par.tga_chip_rev);
+	par->pdev = pdev;
+	par->tga_mem_base = mem_base;
+	par->tga_fb_base = mem_base + fb_offset_presets[tga_type];
+	par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
+	par->tga_type = tga_type;
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &par->tga_chip_rev);
 
 	/* Setup framebuffer.  */
-	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
-                          FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
-	all->info.fbops = &tgafb_ops;
-	all->info.screen_base = all->par.tga_fb_base;
-	all->info.par = &all->par;
-	all->info.pseudo_palette = all->pseudo_palette;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
+		      FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
+	info->fbops = &tgafb_ops;
+	info->screen_base = par->tga_fb_base;
+	info->pseudo_palette = (void *)(par + 1);
 
 	/* This should give a reasonable default video mode.  */
 
-	ret = fb_find_mode(&all->info.var, &all->info, mode_option,
-			   NULL, 0, NULL,
+	ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL,
 			   tga_type == TGA_TYPE_8PLANE ? 8 : 32);
 	if (ret == 0 || ret == 4) {
 		printk(KERN_ERR "tgafb: Could not find valid video mode\n");
@@ -1412,29 +1424,28 @@
 		goto err1;
 	}
 
-	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
 		printk(KERN_ERR "tgafb: Could not allocate color map\n");
 		ret = -ENOMEM;
 		goto err1;
 	}
 
-	tgafb_set_par(&all->info);
-	tgafb_init_fix(&all->info);
+	tgafb_set_par(info);
+	tgafb_init_fix(info);
 
-	all->info.device = &pdev->dev;
-	if (register_framebuffer(&all->info) < 0) {
+	if (register_framebuffer(info) < 0) {
 		printk(KERN_ERR "tgafb: Could not register framebuffer\n");
 		ret = -EINVAL;
 		goto err1;
 	}
 
 	printk(KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
-	       all->par.tga_chip_rev);
+	       par->tga_chip_rev);
 	printk(KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n",
 	       pdev->bus->number, PCI_SLOT(pdev->devfn),
 	       PCI_FUNC(pdev->devfn));
 	printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n",
-	       all->info.node, all->info.fix.id, bar0_start);
+	       info->node, info->fix.id, bar0_start);
 
 	return 0;
 
@@ -1443,11 +1454,11 @@
 		iounmap(mem_base);
 	release_mem_region(bar0_start, bar0_len);
  err0:
-	kfree(all);
+	framebuffer_release(info);
 	return ret;
 }
 
-static void __exit
+static void __devexit
 tgafb_pci_unregister(struct pci_dev *pdev)
 {
 	struct fb_info *info = pci_get_drvdata(pdev);
@@ -1456,22 +1467,21 @@
 	if (!info)
 		return;
 	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
 	iounmap(par->tga_mem_base);
 	release_mem_region(pci_resource_start(pdev, 0),
 			   pci_resource_len(pdev, 0));
-	kfree(info);
+	framebuffer_release(info);
 }
 
-#ifdef MODULE
-static void __exit
+static void __devexit
 tgafb_exit(void)
 {
 	pci_unregister_driver(&tgafb_driver);
 }
-#endif /* MODULE */
 
 #ifndef MODULE
-int __init
+static int __devinit
 tgafb_setup(char *arg)
 {
 	char *this_opt;
@@ -1493,7 +1503,7 @@
 }
 #endif /* !MODULE */
 
-int __init
+static int __devinit
 tgafb_init(void)
 {
 #ifndef MODULE
@@ -1511,10 +1521,7 @@
  */
 
 module_init(tgafb_init);
-
-#ifdef MODULE
 module_exit(tgafb_exit);
-#endif
 
 MODULE_DESCRIPTION("framebuffer driver for TGA chipset");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 6aff63d..ec4c7dc 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -70,7 +70,8 @@
 		unsigned char	ClockingMode;	  /* Seq-Controller:01h */
 	} vga_state;
 	struct vgastate state;
-	atomic_t ref_count;
+	struct mutex open_lock;
+	unsigned int ref_count;
 	int palette_blanked, vesa_blanked, mode, isVGA;
 	u8 misc, pel_msk, vss, clkdiv;
 	u8 crtc[VGA_CRT_C];
@@ -300,28 +301,33 @@
 static int vga16fb_open(struct fb_info *info, int user)
 {
 	struct vga16fb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
-	if (!cnt) {
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
 			VGA_SAVE_CMAP;
 		save_vga(&par->state);
 	}
-	atomic_inc(&par->ref_count);
+	par->ref_count++;
+	mutex_unlock(&par->open_lock);
+
 	return 0;
 }
 
 static int vga16fb_release(struct fb_info *info, int user)
 {
 	struct vga16fb_par *par = info->par;
-	int cnt = atomic_read(&par->ref_count);
 
-	if (!cnt)
+	mutex_lock(&par->open_lock);
+	if (!par->ref_count) {
+		mutex_unlock(&par->open_lock);
 		return -EINVAL;
-	if (cnt == 1)
+	}
+	if (par->ref_count == 1)
 		restore_vga(&par->state);
-	atomic_dec(&par->ref_count);
+	par->ref_count--;
+	mutex_unlock(&par->open_lock);
 
 	return 0;
 }
@@ -1357,6 +1363,7 @@
 	printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
 	par = info->par;
 
+	mutex_init(&par->open_lock);
 	par->isVGA = ORIG_VIDEO_ISVGA;
 	par->palette_blanked = 0;
 	par->vesa_blanked = 0;
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c
deleted file mode 100644
index b9fb6fb..0000000
--- a/drivers/video/virgefb.c
+++ /dev/null
@@ -1,2526 +0,0 @@
-/*
- * linux/drivers/video/virgefb.c -- CyberVision64/3D frame buffer device
- *
- *    Copyright (C) 1997 André Heynatz
- *
- *
- * This file is based on the CyberVision frame buffer device (cyberfb.c):
- *
- *    Copyright (C) 1996 Martin Apel
- *                       Geert Uytterhoeven
- *
- * Zorro II additions :
- *
- *    Copyright (C) 1998-2000 Christian T. Steigies
- *
- * Initialization additions :
- *
- *    Copyright (C) 1998-2000 Ken Tyler
- *
- * Parts of the Initialization code are based on Cyberfb.c by Allan Bair,
- * and on the NetBSD CyberVision64 frame buffer driver by Michael Teske who gave
- * permission for its use.
- *
- * Many thanks to Frank Mariak for his assistance with ZORRO 2 access and other
- * mysteries.
- *
- *
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#undef VIRGEFBDEBUG
-#undef VIRGEFBDUMP
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/zorro.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/amigahw.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb32.h>
-
-#include "virgefb.h"
-
-#ifdef VIRGEFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#ifdef VIRGEFBDUMP
-static void cv64_dump(void);
-#define DUMP cv64_dump()
-#else
-#define DUMP
-#endif
-
-/*
- *	Macros for register access and zorro control
- */
-
-static inline void mb_inline(void) { mb(); }	/* for use in comma expressions */
-
-/* Set zorro 2 map */
-
-#define SelectIO \
-	mb(); \
-	if (on_zorro2) { \
-		(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x04)) = 0x01); \
-		mb(); \
-	}
-
-#define	SelectMMIO \
-	mb(); \
-	if (on_zorro2) { \
-		(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x04)) = 0x02); \
-		mb(); \
-	}
-
-#define	SelectCFG \
-	mb(); \
-	if (on_zorro2) { \
-		(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x04)) = 0x03); \
-		mb(); \
-	}
-
-/* Set pass through, 0 = amiga, !=0 = cv64/3d */
-
-#define SetVSwitch(x) \
-	mb(); \
-	(*(volatile u16 *)((u8 *)(vcode_switch_base)) = \
-	(u16)(x ? 0 : 1)); \
-	mb();
-
-/* Zorro2 endian 'aperture' */
-
-#define ENDIAN_BYTE	2
-#define ENDIAN_WORD	1
-#define ENDIAN_LONG	0
-
-#define Select_Zorro2_FrameBuffer(x) \
-	do { \
-		if (on_zorro2) { \
-			mb(); \
-			(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x08)) = \
-			(x * 0x40)); \
-			mb(); \
-		} \
-	} while (0)
-
-/* SetPortVal - only used for interrupt enable (not yet implemented) */
-
-#if 0
-#define SetPortVal(x) \
-	mb(); \
-	(*(volatile u16 *)((u8 *)(vcode_switch_base + 0x0c)) = \
-	(u16)x); \
-	mb();
-#endif
-
-/* IO access */
-
-#define byte_access_io(x)	(((x) & 0x3ffc) | (((x) & 3)^3) | (((x) & 3) <<14))
-#define byte_access_mmio(x)	(((x) & 0xfffc) | (((x) & 3)^3))
-
-/* Write 8 bit VGA register - used once for chip wakeup */
-
-#define wb_vgaio(reg, dat) \
-	SelectIO; \
-	(*(volatile u8 *)(vgaio_regs + ((u32)byte_access_io(reg) & 0xffff)) = \
-	(dat & 0xff)); \
-	SelectMMIO;
-
-/* Read 8 bit VGA register - only used in dump (SelectIO not needed on read ?) */
-
-#ifdef VIRGEFBDUMP
-#define rb_vgaio(reg) \
-	({ \
-	u8 __zzyzx; \
-	SelectIO; \
-	__zzyzx = (*(volatile u8 *)((vgaio_regs)+(u32)byte_access_io(reg))); \
-	SelectMMIO; \
-	__zzyzx; \
-	})
-#endif
-
-/* MMIO access */
-
-/* Read 8 bit MMIO register */
-
-#define rb_mmio(reg) \
-	(mb_inline(), \
-	(*(volatile u8 *)(mmio_regs + 0x8000 + (u32)byte_access_mmio(reg))))
-
-/* Write 8 bit MMIO register */
-
-#define wb_mmio(reg,dat) \
-	mb(); \
-	(*(volatile u8 *)(mmio_regs + 0x8000 + (byte_access_mmio((reg) & 0xffff))) = \
-	(dat & 0xff)); \
-	mb();
-
-/* Read 32 bit MMIO register */
-
-#define rl_mmio(reg) \
-	(mb_inline(), \
-	(*((volatile u32 *)((u8 *)((mmio_regs + (on_zorro2 ? 0x20000 : 0)) + (reg))))))
-
-/* Write 32 bit MMIO register */
-
-#define wl_mmio(reg,dat) \
-	mb(); \
-	((*(volatile u32 *)((u8 *)((mmio_regs + (on_zorro2 ? 0x20000 : 0)) + (reg)))) = \
-	(u32)(dat)); \
-	mb();
-
-/* Write to virge graphics register */
-
-#define wgfx(reg, dat)	do { wb_mmio(GCT_ADDRESS, (reg)); wb_mmio(GCT_ADDRESS_W, (dat)); } while (0)
-
-/* Write to virge sequencer register */
-
-#define wseq(reg, dat)	do { wb_mmio(SEQ_ADDRESS, (reg)); wb_mmio(SEQ_ADDRESS_W, (dat)); } while (0)
-
-/* Write to virge CRT controller register */
-
-#define wcrt(reg, dat)	do { wb_mmio(CRT_ADDRESS, (reg)); wb_mmio(CRT_ADDRESS_W, (dat)); } while (0)
-
-/* Write to virge attribute register */
-
-#define watr(reg, dat) \
-	do { \
-		volatile unsigned char watr_tmp; \
-		watr_tmp = rb_mmio(ACT_ADDRESS_RESET); \
-		wb_mmio(ACT_ADDRESS_W, (reg)); \
-		wb_mmio(ACT_ADDRESS_W, (dat)); \
-		udelay(10); \
-	} while (0)
-
-/* end of macros */
-
-struct virgefb_par {
-   struct fb_var_screeninfo var;
-   __u32 type;
-   __u32 type_aux;
-   __u32 visual;
-   __u32 line_length;
-};
-
-static struct virgefb_par current_par;
-
-static int current_par_valid = 0;
-
-static struct display disp;
-static struct fb_info fb_info;
-
-static union {
-#ifdef FBCON_HAS_CFB16
-    u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-    u32 cfb32[16];
-#endif
-} fbcon_cmap;
-
-/*
- *    Switch for Chipset Independency
- */
-
-static struct fb_hwswitch {
-
-   /* Initialisation */
-
-   int (*init)(void);
-
-   /* Display Control */
-
-   int (*encode_fix)(struct fb_fix_screeninfo *fix, struct virgefb_par *par);
-   int (*decode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par);
-   int (*encode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par);
-   int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
-                    u_int *transp, struct fb_info *info);
-   void (*blank)(int blank);
-} *fbhw;
-
-static unsigned char blit_maybe_busy = 0;
-
-/*
- *    Frame Buffer Name
- */
-
-static char virgefb_name[16] = "CyberVision/3D";
-
-/*
- *    CyberVision64/3d Graphics Board
- */
-
-static unsigned char virgefb_colour_table [256][3];
-static unsigned long v_ram;
-static unsigned long v_ram_size;
-static volatile unsigned char *mmio_regs;
-static volatile unsigned char *vgaio_regs;
-
-static unsigned long v_ram_phys;
-static unsigned long mmio_regs_phys;
-static unsigned long vcode_switch_base;
-static unsigned char on_zorro2;
-
-/*
- * Offsets from start of video ram to appropriate ZIII aperture
- */
-
-#ifdef FBCON_HAS_CFB8
-#define CYBMEM_OFFSET_8  0x800000	/* BGRX */
-#endif
-#ifdef FBCON_HAS_CFB16
-#define CYBMEM_OFFSET_16 0x400000	/* GBXR */
-#endif
-#ifdef FBCON_HAS_CFB32
-#define CYBMEM_OFFSET_32 0x000000	/* XRGB */
-#endif
-
-/*
- *    MEMCLOCK was 32MHz, 64MHz works, 72MHz doesn't (on my board)
- */
-
-#define MEMCLOCK 50000000
-
-/*
- *    Predefined Video Modes
- */
-
-static struct {
-    const char *name;
-    struct fb_var_screeninfo var;
-} virgefb_predefined[] __initdata = {
-#ifdef FBCON_HAS_CFB8
-    {
-	"640x480-8", {		/* Cybervision 8 bpp */
-	    640, 480, 640, 480, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 31250, 160, 136, 82, 61, 88, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"768x576-8", {		/* Cybervision 8 bpp */
-	    768, 576, 768, 576, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 29411, 144, 112, 32, 15, 64, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"800x600-8", {		/* Cybervision 8 bpp */
-	    800, 600, 800, 600, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 28571, 168, 104, 22, 1, 48, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-  #if 0 
-	"1024x768-8", {		/* Cybervision 8 bpp */
-	    1024, 768, 1024, 768, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-  #else
-	"1024x768-8", {
-	    1024, 768, 1024, 768, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-   #if 0
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 12500, 184, 40, 40, 2, 96, 1,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
-    #else
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 12699, 176, 16, 28, 1, 96, 3,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
-    #endif
-  #endif
-    }, {
-	"1152x886-8", {		/* Cybervision 8 bpp */
-	    1152, 886, 1152, 886, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 19230, 280, 168, 45, 1, 64, 10,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1280x1024-8", { 	/* Cybervision 8 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-  #if 0
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    }
-  #else
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 7414, 232, 64, 38, 1, 112, 3,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
-  #endif
-    }, {
-	"1600x1200-8", { 	/* Cybervision 8 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-  #if 0
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-  #else
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 6411, 256, 32, 52, 10, 160, 8,
-	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-	    }
-  #endif
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB16
-    {
-	"640x480-16", {		/* Cybervision 16 bpp */
-	    640, 480, 640, 480, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 31250, 152, 144, 82, 61, 88, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"768x576-16", {		/* Cybervision 16 bpp */
-	    768, 576, 768, 576, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 29411, 144, 112, 32, 15, 64, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"800x600-16", {		/* Cybervision 16 bpp */
-	    800, 600, 800, 600, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 28571, 168, 104, 22, 1, 48, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-#if 0
-	"1024x768-16", { 	/* Cybervision 16 bpp */
-	    1024, 768, 1024, 768, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-#else
-         "1024x768-16", {
-             1024, 768, 1024, 768, 0, 0, 16, 0,
-             {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-             0, 0, -1, -1, FB_ACCELF_TEXT, 12500, 184, 40, 40, 2, 96, 1,
-             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-         }
-#endif
-    }, {
-	"1152x886-16", { 	/* Cybervision 16 bpp */
-	    1152, 886, 1152, 886, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 19230, 280, 168, 45, 1, 64, 10,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1280x1024-16", { 	/* Cybervision 16 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1600x1200-16", { 	/* Cybervision 16 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB32
-    {
-	"640x480-32", {		/* Cybervision 32 bpp */
-	    640, 480, 640, 480, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 31250, 160, 136, 82, 61, 88, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-     }, {
-	"768x576-32", {		/* Cybervision 32 bpp */
-	    768, 576, 768, 576, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 29411, 144, 112, 32, 15, 64, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-     }, {
-	"800x600-32", {		/* Cybervision 32 bpp */
-	    800, 600, 800, 600, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-  	    0, 0, -1, -1, FB_ACCELF_TEXT, 28571, 168, 104, 22, 1, 48, 2,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-     }, {
-	"1024x768-32", {	/* Cybervision 32 bpp */
-	    1024, 768, 1024, 768, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1152x886-32", {	/* Cybervision 32 bpp */
-	    1152, 886, 1152, 886, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 19230, 280, 168, 45, 1, 64, 10,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1280x1024-32", {	/* Cybervision 32 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    }, {
-	"1600x1200-32", {	/* Cybervision 32 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_NONINTERLACED
-	    }
-    },
-#endif
-
-/* interlaced modes */
-
-#ifdef FBCON_HAS_CFB8
-    {
-	"1024x768-8i", {	/* Cybervision 8 bpp */
-	    1024, 768, 1024, 768, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1280x1024-8i", {	/* Cybervision 8 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1600x1200-8i", {	/* Cybervision 8 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB16
-    {
-	"1024x768-16i", {	/* Cybervision 16 bpp */
-	    1024, 768, 1024, 768, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 20833, 272, 168, 39, 2, 72, 1,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1280x1024-16i", {	/* Cybervision 16 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1600x1200-16i", {	/* Cybervision 16 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB32
-    {
-	"1024x768-32i", {	/* Cybervision 32 bpp */
-	    1024, 768, 1024, 768, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 22222, 216, 144, 39, 2, 72, 1,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1280x1024-32i", {	/* Cybervision 32 bpp */
-	    1280, 1024, 1280, 1024, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {23, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 17857, 232, 232, 71, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    }, {
-	"1600x1200-32i", {	/* Cybervision 32 bpp */
-	    1600, 1200, 1600, 1200, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 13698, 336, 224, 77, 15, 176, 12,
-	    0, FB_VMODE_INTERLACED
-	    }
-    },
-#endif
-
-/* doublescan modes */
-
-#ifdef FBCON_HAS_CFB8
-    {
-	"320x240-8d", {		/* Cybervision 8 bpp */
-	    320, 240, 320, 240, 0, 0, 8, 0,
-	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 59259, 80, 80, 45, 26, 32, 1,
-	    0, FB_VMODE_DOUBLE
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB16
-    {
-	"320x240-16d", {	/* Cybervision 16 bpp */
-	    320, 240, 320, 240, 0, 0, 16, 0,
-	    {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 59259, 80, 80, 45, 26, 32, 1,
-	    0, FB_VMODE_DOUBLE
-	    }
-    },
-#endif
-
-#ifdef FBCON_HAS_CFB32
-    {
-	"320x240-32d", {	/* Cybervision 32 bpp */
-	    320, 240, 320, 240, 0, 0, 32, 0,
-	    {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {24, 0, 0},
-	    0, 0, -1, -1, FB_ACCELF_TEXT, 59259, 80, 80, 45, 26, 32, 1,
-	    0, FB_VMODE_DOUBLE
-	    }
-    },
-#endif
-};
-
-#define NUM_TOTAL_MODES	ARRAY_SIZE(virgefb_predefined)
-
-/*
- *    Default to 800x600 for video=virge8:, virge16: or virge32:
- */
-
-#ifdef FBCON_HAS_CFB8
-#define VIRGE8_DEFMODE	(2)
-#endif
-
-#ifdef FBCON_HAS_CFB16
-#define VIRGE16_DEFMODE	(9)
-#endif
-
-#ifdef FBCON_HAS_CFB32
-#define VIRGE32_DEFMODE	(16)
-#endif
-
-static struct fb_var_screeninfo virgefb_default;
-static int virgefb_inverse = 0;
-
-/*
- *    Interface used by the world
- */
-
-int virgefb_setup(char*);
-static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info);
-static int virgefb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int virgefb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info);
-static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			   struct fb_info *info);
-static int virgefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info);
-static int virgefb_blank(int blank, struct fb_info *info);
-
-/*
- *    Interface to the low level console driver
- */
-
-int virgefb_init(void);
-static int virgefb_switch(int con, struct fb_info *info);
-static int virgefb_updatevar(int con, struct fb_info *info);
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static struct display_switch fbcon_virge8;
-#endif
-
-#ifdef FBCON_HAS_CFB16
-static struct display_switch fbcon_virge16;
-#endif
-
-#ifdef FBCON_HAS_CFB32
-static struct display_switch fbcon_virge32;
-#endif
-
-/*
- *   Hardware Specific Routines
- */
-
-static int virge_init(void);
-static int virgefb_encode_fix(struct fb_fix_screeninfo *fix,
-				struct virgefb_par *par);
-static int virgefb_decode_var(struct fb_var_screeninfo *var,
-				struct virgefb_par *par);
-static int virgefb_encode_var(struct fb_var_screeninfo *var,
-				struct virgefb_par *par);
-static int virgefb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-				u_int *transp, struct fb_info *info);
-static void virgefb_gfx_on_off(int blank);
-static inline void virgefb_wait_for_idle(void);
-static void virgefb_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
-		u_short width, u_short height, u_short stride, u_short depth);
-static void virgefb_RectFill(u_short x, u_short y, u_short width, u_short height,
-		u_short color, u_short stride, u_short depth);
-
-/*
- *    Internal routines
- */
-
-static void virgefb_get_par(struct virgefb_par *par);
-static void virgefb_set_par(struct virgefb_par *par);
-static int virgefb_do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
-static void virgefb_set_disp(int con, struct fb_info *info);
-static int virgefb_get_video_mode(const char *name);
-static void virgefb_set_video(struct fb_var_screeninfo *var);
-
-/*
- *    Additions for Initialization
- */
-
-static void virgefb_load_video_mode(struct fb_var_screeninfo *video_mode);
-static int cv3d_has_4mb(void);
-static unsigned short virgefb_compute_clock(unsigned long freq);
-static inline unsigned char rattr(short);
-static inline unsigned char rseq(short);
-static inline unsigned char rcrt(short);
-static inline unsigned char rgfx(short);
-static inline void gfx_on_off(int toggle);
-static void virgefb_pci_init(void);
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-/*
- *	Functions for register access
- */
-
-/* Read attribute controller register */
-
-static inline unsigned char rattr(short idx)
-{
-	volatile unsigned char rattr_tmp;
-
-	rattr_tmp = rb_mmio(ACT_ADDRESS_RESET);
-	wb_mmio(ACT_ADDRESS_W, idx);
-	return (rb_mmio(ACT_ADDRESS_R));
-}
-
-/* Read sequencer register */
-
-static inline unsigned char rseq(short idx)
-{
-	wb_mmio(SEQ_ADDRESS, idx);
-	return (rb_mmio(SEQ_ADDRESS_R));
-}
-
-/* Read CRT controller register */
-
-static inline unsigned char rcrt(short idx)
-{
-	wb_mmio(CRT_ADDRESS, idx);
-	return (rb_mmio(CRT_ADDRESS_R));
-}
-
-/* Read graphics controller register */
-
-static inline unsigned char rgfx(short idx)
-{
-	wb_mmio(GCT_ADDRESS, idx);
-	return (rb_mmio(GCT_ADDRESS_R));
-}
-
-
-/*
- *	Initialization
- */
-
-/* PCI init */
-
-void virgefb_pci_init(void) {
-
-	DPRINTK("ENTER\n");
-
-	SelectCFG;
-
-	if (on_zorro2) {
-		*((short *)(vgaio_regs + 0x00000010)) = 0;
-		*((long  *)(vgaio_regs + 0x00000004)) = 0x02000003;
-	} else {
-		*((short *)(vgaio_regs + 0x000e0010)) = 0;
-		*((long  *)(vgaio_regs + 0x000e0004)) = 0x02000003;
-	}
-
-	/* SelectIO is in wb_vgaio macro */
-	wb_vgaio(SREG_VIDEO_SUBS_ENABLE, 0x01);
-	/* SelectMMIO is in wb_vgaio macro */
-
-	DPRINTK("EXIT\n");
-
-	return;
-}
-
-/* 
- * Initalize all mode independent regs, find mem size and clear mem
-*/
-
-static int virge_init(void)
-{
-	int i;
-	unsigned char tmp;
-
-	DPRINTK("ENTER\n");
-
-	virgefb_pci_init();
-
-	wb_mmio(GREG_MISC_OUTPUT_W, 0x07);	/* colour, ram enable, clk sel */
-
-	wseq(SEQ_ID_UNLOCK_EXT, 0x06);		/* unlock extensions */
-	tmp = rb_mmio(GREG_MISC_OUTPUT_R);
-	wcrt(CRT_ID_REGISTER_LOCK_1, 0x48);	/* unlock CR2D to CR3F */
-
-	wcrt(CRT_ID_BACKWAD_COMP_1, 0x00);	/* irq disable */
-
-	wcrt(CRT_ID_REGISTER_LOCK_2, 0xa5);	/* unlock CR40 to CRFF and more */
-	wcrt(CRT_ID_REGISTER_LOCK,0x00);	/* unlock h and v timing */
-	wcrt(CRT_ID_SYSTEM_CONFIG, 0x01);	/* unlock enhanced programming registers */
-
-	wb_mmio(GREG_FEATURE_CONTROL_W, 0x00);
-
-	wcrt(CRT_ID_EXT_MISC_CNTL, 0x00);	/* b2 = 0 to allow VDAC mmio access */
-#if 0
-	/* write strap options ... ? */
-	wcrt(CRT_ID_CONFIG_1, 0x08);
-	wcrt(CRT_ID_CONFIG_2, 0xff);		/* 0x0x2 bit needs to be set ?? */
-	wcrt(CRT_ID_CONFIG_3, 0x0f);
-	wcrt(CRT_ID_CONFIG_4, 0x1a);
-#endif
-	wcrt(CRT_ID_EXT_MISC_CNTL_1, 0x82);	 /* PCI DE and software reset S3D engine */
-	/* EXT_MISC_CNTL_1, CR66 bit 0 should be the same as bit 0 MR_ADVANCED_FUNCTION_CONTROL - check */
-	wl_mmio(MR_ADVANCED_FUNCTION_CONTROL, 0x00000011); /* enhanced mode, linear addressing */
-
-/* crtc registers */
-
-	wcrt(CRT_ID_PRESET_ROW_SCAN, 0x00);
-
-	/* Disable h/w cursor */
-
-	wcrt(CRT_ID_CURSOR_START, 0x00);
-	wcrt(CRT_ID_CURSOR_END, 0x00);
-	wcrt(CRT_ID_START_ADDR_HIGH, 0x00);
-	wcrt(CRT_ID_START_ADDR_LOW, 0x00);
-	wcrt(CRT_ID_CURSOR_LOC_HIGH, 0x00);
-	wcrt(CRT_ID_CURSOR_LOC_LOW, 0x00);
-	wcrt(CRT_ID_EXT_MODE, 0x00);
-	wcrt(CRT_ID_HWGC_MODE, 0x00);
-	wcrt(CRT_ID_HWGC_ORIGIN_X_HI, 0x00);
-	wcrt(CRT_ID_HWGC_ORIGIN_X_LO, 0x00);
-	wcrt(CRT_ID_HWGC_ORIGIN_Y_HI, 0x00);
-	wcrt(CRT_ID_HWGC_ORIGIN_Y_LO, 0x00);
-	i = rcrt(CRT_ID_HWGC_MODE);
-	wcrt(CRT_ID_HWGC_FG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_FG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_FG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_BG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_BG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_BG_STACK, 0x00);
-	wcrt(CRT_ID_HWGC_START_AD_HI, 0x00);
-	wcrt(CRT_ID_HWGC_START_AD_LO, 0x00);
-	wcrt(CRT_ID_HWGC_DSTART_X, 0x00);
-	wcrt(CRT_ID_HWGC_DSTART_Y, 0x00);
-
-	wcrt(CRT_ID_UNDERLINE_LOC, 0x00);
-
-	wcrt(CRT_ID_MODE_CONTROL, 0xe3);
-	wcrt(CRT_ID_BACKWAD_COMP_2, 0x22);	/* blank bdr bit 5 blanking only on 8 bit */
-
-	wcrt(CRT_ID_EX_SYNC_1, 0x00);
-
-	/* memory */
-
-	wcrt(CRT_ID_EXT_SYS_CNTL_3, 0x00);
-	wcrt(CRT_ID_MEMORY_CONF, 0x08);		/* config enhanced map */
-	wcrt(CRT_ID_EXT_MEM_CNTL_1, 0x08);	/* MMIO Select (0x0c works as well)*/
-	wcrt(CRT_ID_EXT_MEM_CNTL_2, 0x02);	/* why 02 big endian 00 works ? */
-	wcrt(CRT_ID_EXT_MEM_CNTL_4, 0x9f);	/* config big endian - 0x00 ?  */
-	wcrt(CRT_ID_LAW_POS_HI, 0x00);
-	wcrt(CRT_ID_LAW_POS_LO, 0x00);
-	wcrt(CRT_ID_EXT_MISC_CNTL_1, 0x81);
-	wcrt(CRT_ID_MISC_1, 0x90);		/* must follow CRT_ID_EXT_MISC_CNTL_1 */
-	wcrt(CRT_ID_LAW_CNTL, 0x13);		/* force 4 Meg for test */
-	if (cv3d_has_4mb()) {
-		v_ram_size = 0x00400000;
-		wcrt(CRT_ID_LAW_CNTL, 0x13);	/* 4 MB */
-	} else {
-		v_ram_size = 0x00200000;
-		wcrt(CRT_ID_LAW_CNTL, 0x12); 	/* 2 MB */
-	}
-
-	if (on_zorro2)
-		v_ram_size -= 0x60000;		/* we need some space for the registers */
-
-	wcrt(CRT_ID_EXT_SYS_CNTL_4, 0x00);
-	wcrt(CRT_ID_EXT_DAC_CNTL, 0x00);	/* 0x10 for X11 cursor mode */
-
-/* sequencer registers */
-
-	wseq(SEQ_ID_CLOCKING_MODE, 0x01);	/* 8 dot clock */
-	wseq(SEQ_ID_MAP_MASK, 0xff);
-	wseq(SEQ_ID_CHAR_MAP_SELECT, 0x00);
-	wseq(SEQ_ID_MEMORY_MODE, 0x02);
-	wseq(SEQ_ID_RAMDAC_CNTL, 0x00);
-	wseq(SEQ_ID_SIGNAL_SELECT, 0x00);
-	wseq(SEQ_ID_EXT_SEQ_REG9, 0x00);	/* MMIO and PIO reg access enabled */
-	wseq(SEQ_ID_EXT_MISC_SEQ, 0x00);
-	wseq(SEQ_ID_CLKSYN_CNTL_1, 0x00);
-	wseq(SEQ_ID_EXT_SEQ, 0x00);
-
-/* graphic registers */
-
-	wgfx(GCT_ID_SET_RESET, 0x00);
-	wgfx(GCT_ID_ENABLE_SET_RESET, 0x00);
-	wgfx(GCT_ID_COLOR_COMPARE, 0x00);
-	wgfx(GCT_ID_DATA_ROTATE, 0x00);
-	wgfx(GCT_ID_READ_MAP_SELECT, 0x00);
-	wgfx(GCT_ID_GRAPHICS_MODE, 0x40);
-	wgfx(GCT_ID_MISC, 0x01);
-	wgfx(GCT_ID_COLOR_XCARE, 0x0f);
-	wgfx(GCT_ID_BITMASK, 0xff);
-
-/* attribute  registers */
-
-	for(i = 0; i <= 15; i++)
-		watr(ACT_ID_PALETTE0 + i, i);
-	watr(ACT_ID_ATTR_MODE_CNTL, 0x41);
-	watr(ACT_ID_OVERSCAN_COLOR, 0xff);
-	watr(ACT_ID_COLOR_PLANE_ENA, 0x0f);
-	watr(ACT_ID_HOR_PEL_PANNING, 0x00);
-	watr(ACT_ID_COLOR_SELECT, 0x00);
-
-	wb_mmio(VDAC_MASK, 0xff);
-
-/* init local cmap as greyscale levels */
-
-	for (i = 0; i < 256; i++) {
-		virgefb_colour_table [i][0] = i;
-		virgefb_colour_table [i][1] = i;
-		virgefb_colour_table [i][2] = i;
-	}
-
-/* clear framebuffer memory */
-
-	memset((char*)v_ram, 0x00, v_ram_size);
-
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    This function should fill in the `fix' structure based on the
- *    values in the `par' structure.
- */
-
-static int virgefb_encode_fix(struct fb_fix_screeninfo *fix,
-			    struct virgefb_par *par)
-{
-	DPRINTK("ENTER set video phys addr\n");
-
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, virgefb_name);
-	if (on_zorro2)
-		fix->smem_start = v_ram_phys;
-	switch (par->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-		case 8:
-			if (on_zorro2)
-				Select_Zorro2_FrameBuffer(ENDIAN_BYTE);
-			else
-				fix->smem_start = (v_ram_phys + CYBMEM_OFFSET_8);
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16:
-			if (on_zorro2)
-				Select_Zorro2_FrameBuffer(ENDIAN_WORD);
-			else
-				fix->smem_start = (v_ram_phys + CYBMEM_OFFSET_16);
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32:
-			if (on_zorro2)
-				Select_Zorro2_FrameBuffer(ENDIAN_LONG);
-			else
-				fix->smem_start = (v_ram_phys + CYBMEM_OFFSET_32);
-			break;
-#endif
-	}
-
-	fix->smem_len = v_ram_size;
-	fix->mmio_start = mmio_regs_phys;
-	fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */
-
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
-	if (par->var.bits_per_pixel == 8)
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-		fix->visual = FB_VISUAL_TRUECOLOR;
-
-	fix->xpanstep = 0;
-	fix->ypanstep = 0;
-	fix->ywrapstep = 0;
-	fix->line_length = par->var.xres_virtual*par->var.bits_per_pixel/8;
-	fix->accel = FB_ACCEL_S3_VIRGE;
-	DPRINTK("EXIT v_ram_phys = 0x%8.8lx\n", (unsigned long)fix->smem_start);
-	return 0;
-}
-
-
-/*
- *	Fill the `par' structure based on the values in `var'.
- *	TODO: Verify and adjust values, return -EINVAL if bad.
- */
-
-static int virgefb_decode_var(struct fb_var_screeninfo *var,
-			    struct virgefb_par *par)
-{
-	DPRINTK("ENTER\n");
-	par->var.xres = var->xres;
-	par->var.yres = var->yres;
-	par->var.xres_virtual = var->xres_virtual;
-	par->var.yres_virtual = var->yres_virtual;
-	/* roundup and validate */
-	par->var.xres = (par->var.xres+7) & ~7;
-	par->var.xres_virtual = (par->var.xres_virtual+7) & ~7;
-	if (par->var.xres_virtual < par->var.xres)
-		par->var.xres_virtual = par->var.xres;
-	if (par->var.yres_virtual < par->var.yres)
-		par->var.yres_virtual = par->var.yres;
-	par->var.xoffset = var->xoffset;
-	par->var.yoffset = var->yoffset;
-	par->var.bits_per_pixel = var->bits_per_pixel;
-	if (par->var.bits_per_pixel <= 8)
-		par->var.bits_per_pixel = 8;
-	else if (par->var.bits_per_pixel <= 16)
-		par->var.bits_per_pixel = 16;
-	else
-		par->var.bits_per_pixel = 32;
-#ifndef FBCON_HAS_CFB32
-	if (par->var.bits_per_pixel == 32)
-		par->var.bits_per_pixel = 16;
-#endif
-#ifndef FBCON_HAS_CFB16
-	if (par->var.bits_per_pixel == 16)
-		par->var.bits_per_pixel = 8;
-#endif
-	par->var.grayscale = var->grayscale;
-	par->var.red = var->red;
-	par->var.green = var->green;
-	par->var.blue = var->blue;
-	par->var.transp = var->transp;
-	par->var.nonstd = var->nonstd;
-	par->var.activate = var->activate;
-	par->var.height = var->height;
-	par->var.width = var->width;
-	if (var->accel_flags & FB_ACCELF_TEXT) {
-		par->var.accel_flags = FB_ACCELF_TEXT;
-	} else {
-		par->var.accel_flags = 0;
-	}
-	par->var.pixclock = var->pixclock;
-	par->var.left_margin = var->left_margin;
-	par->var.right_margin = var->right_margin;
-	par->var.upper_margin = var->upper_margin;
-	par->var.lower_margin = var->lower_margin;
-	par->var.hsync_len = var->hsync_len;
-	par->var.vsync_len = var->vsync_len;
-	par->var.sync = var->sync;
-	par->var.vmode = var->vmode;
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *	Fill the `var' structure based on the values in `par' and maybe
- *	other values read out of the hardware.
- */
-
-static int virgefb_encode_var(struct fb_var_screeninfo *var,
-				struct virgefb_par *par)
-{
-	DPRINTK("ENTER\n");
-	memset(var, 0, sizeof(struct fb_var_screeninfo));	/* need this ? */
-	var->xres = par->var.xres;
-	var->yres = par->var.yres;
-	var->xres_virtual = par->var.xres_virtual;
-	var->yres_virtual = par->var.yres_virtual;
-	var->xoffset = par->var.xoffset;
-	var->yoffset = par->var.yoffset;
-	var->bits_per_pixel = par->var.bits_per_pixel;
-	var->grayscale = par->var.grayscale;
-	var->red = par->var.red;
-	var->green = par->var.green;
-	var->blue = par->var.blue;
-	var->transp = par->var.transp;
-	var->nonstd = par->var.nonstd;
-	var->activate = par->var.activate;
-	var->height = par->var.height;
-	var->width = par->var.width;
-	var->accel_flags = par->var.accel_flags;
-	var->pixclock = par->var.pixclock;
-	var->left_margin = par->var.left_margin;
-	var->right_margin = par->var.right_margin;
-	var->upper_margin = par->var.upper_margin;
-	var->lower_margin = par->var.lower_margin;
-	var->hsync_len = par->var.hsync_len;
-	var->vsync_len = par->var.vsync_len;
-	var->sync = par->var.sync;
-	var->vmode = par->var.vmode;
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *    Set a single color register. The values supplied are already
- *    rounded down to the hardware's capabilities (according to the
- *    entries in the var structure). Return != 0 for invalid regno.
- */
-
-static int virgefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	if (((current_par.var.bits_per_pixel==8) && (regno>255)) ||
-		((current_par.var.bits_per_pixel!=8) && (regno>15))) {
-			DPRINTK("EXIT\n");
-			return 1;
-	}
-	if (((current_par.var.bits_per_pixel==8) && (regno<256)) ||
-			((current_par.var.bits_per_pixel!=8) && (regno<16))) {
-		virgefb_colour_table [regno][0] = red >> 10;
-		virgefb_colour_table [regno][1] = green >> 10;
-		virgefb_colour_table [regno][2] = blue >> 10;
-	}
-
-	switch (current_par.var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-		case 8:
-			wb_mmio(VDAC_ADDRESS_W, (unsigned char)regno);
-			wb_mmio(VDAC_DATA, ((unsigned char)(red >> 10)));
-			wb_mmio(VDAC_DATA, ((unsigned char)(green >> 10)));
-			wb_mmio(VDAC_DATA, ((unsigned char)(blue >> 10)));
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16:
-			fbcon_cmap.cfb16[regno] =
-				((red  & 0xf800) |
-				((green & 0xfc00) >> 5) |
-				((blue  & 0xf800) >> 11));
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32:
-			fbcon_cmap.cfb32[regno] =
-				/* transp = 0's or 1's  ? */
-				(((red  & 0xff00) << 8) |
-				((green & 0xff00) >> 0) |
-				((blue  & 0xff00) >> 8));
-			break;
-#endif
-	}
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Read a single color register and split it into
- *    colors/transparent. Return != 0 for invalid regno.
- */
-
-static int virgefb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			   u_int *transp, struct fb_info *info)
-{
-	int t;
-
-	DPRINTK("ENTER\n");
-	if (regno > 255) {
-		DPRINTK("EXIT\n");
-		return 1;
-	}
-	if (((current_par.var.bits_per_pixel==8) && (regno<256)) ||
-			((current_par.var.bits_per_pixel!=8) && (regno<16))) {
-
-		t = virgefb_colour_table [regno][0];
-		*red = (t<<10) | (t<<4) | (t>>2);
-		t = virgefb_colour_table [regno][1];
-		*green = (t<<10) | (t<<4) | (t>>2);
-		t = virgefb_colour_table [regno][2];
-		*blue = (t<<10) | (t<<4) | (t>>2);
-	}
-	*transp = 0;
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    (Un)Blank the screen
- */
-
-static void virgefb_gfx_on_off(int blank)
-{
-	DPRINTK("ENTER\n");
-	gfx_on_off(blank);
-	DPRINTK("EXIT\n");
-}
-
-/*
- * CV3D low-level support
- */
-
-
-static inline void wait_3d_fifo_slots(int n)	/* WaitQueue */
-{
-	do {
-		mb();
-	} while (((rl_mmio(MR_SUBSYSTEM_STATUS_R) >> 8) & 0x1f) < (n + 2));
-}
-
-static inline void virgefb_wait_for_idle(void)	/* WaitIdle */
-{
-	while(!(rl_mmio(MR_SUBSYSTEM_STATUS_R) & 0x2000)) ;
-	blit_maybe_busy = 0;
-}
-
- /*
-  * BitBLT - Through the Plane
-  */
-
-static void virgefb_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
-			u_short width, u_short height, u_short stride, u_short depth)
-{
-	unsigned int blitcmd = S3V_BITBLT | S3V_DRAW | S3V_BLT_COPY;
-
-	switch (depth) {
-#ifdef FBCON_HAS_CFB8
-		case 8 :
-			blitcmd |= S3V_DST_8BPP;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16 :
-			blitcmd |= S3V_DST_16BPP;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32 :
-			/* 32 bit uses 2 by 16 bit values, see fbcon_virge32_bmove */
-			blitcmd |= S3V_DST_16BPP;
-			break;
-#endif
-	}
-
-	/* Set drawing direction */
-	/* -Y, X maj, -X (default) */
-	if (curx > destx) {
-		blitcmd |= (1 << 25);  /* Drawing direction +X */
-	} else {
-		curx  += (width - 1);
-		destx += (width - 1);
-	}
-
-	if (cury > desty) {
-		blitcmd |= (1 << 26);  /* Drawing direction +Y */
-	} else {
-		cury  += (height - 1);
-		desty += (height - 1);
-	}
-
-	wait_3d_fifo_slots(8);		/* wait on fifo slots for 8 writes */
-
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	blit_maybe_busy = 1;
-
-	wl_mmio(BLT_PATTERN_COLOR, 1);	/* pattern fb color */
-	wl_mmio(BLT_MONO_PATTERN_0, ~0);
-	wl_mmio(BLT_MONO_PATTERN_1, ~0);
-	wl_mmio(BLT_SIZE_X_Y, ((width << 16) | height));
-	wl_mmio(BLT_SRC_X_Y, ((curx << 16)  | cury));
-	wl_mmio(BLT_DEST_X_Y, ((destx << 16) | desty));
-	wl_mmio(BLT_SRC_DEST_STRIDE, (((stride << 16) | stride) /* & 0x0ff80ff8 */)); /* why is this needed now ? */
-	wl_mmio(BLT_COMMAND_SET, blitcmd);
-}
-
-/*
- * Rectangle Fill Solid
- */
-
-static void virgefb_RectFill(u_short x, u_short y, u_short width, u_short height,
-			u_short color,  u_short stride, u_short depth)
-{
-	unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW |
-		S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25);
-
-	switch (depth) {
-#ifdef FBCON_HAS_CFB8
-		case 8 :
-			blitcmd |= S3V_DST_8BPP;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16 :
-			blitcmd |= S3V_DST_16BPP;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32 :
-			/* 32 bit uses 2 times 16 bit values, see fbcon_virge32_clear */
-			blitcmd |= S3V_DST_16BPP;
-			break;
-#endif
-	}
-
-	wait_3d_fifo_slots(5);		/* wait on fifo slots for 5 writes */
-
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	blit_maybe_busy = 1;
-
-	wl_mmio(BLT_PATTERN_COLOR, (color & 0xff));
-	wl_mmio(BLT_SIZE_X_Y, ((width << 16) | height));
-	wl_mmio(BLT_DEST_X_Y, ((x << 16) | y));
-	wl_mmio(BLT_SRC_DEST_STRIDE, (((stride << 16) | stride) /* & 0x0ff80ff8 */));
-	wl_mmio(BLT_COMMAND_SET, blitcmd);
-}
-
-/*
- * Move cursor to x, y
- */
-
-#if 0
-static void virgefb_move_cursor(u_short x, u_short y)
-{
-	DPRINTK("Yuck .... MoveCursor on a 3D\n");
-	return 0;
-}
-#endif
-
-/* -------------------- Interfaces to hardware functions -------------------- */
-
-static struct fb_hwswitch virgefb_hw_switch = {
-	.init		= virge_init,
-	.encode_fix	= virgefb_encode_fix,
-	.decode_var	= virgefb_decode_var,
-	.encode_var	= virgefb_encode_var,
-	.getcolreg	= virgefb_getcolreg,
-	.blank		= virgefb_gfx_on_off
-};
-
-
-/* -------------------- Generic routines ------------------------------------ */
-
-
-/*
- *    Fill the hardware's `par' structure.
- */
-
-static void virgefb_get_par(struct virgefb_par *par)
-{
-	DPRINTK("ENTER\n");
-	if (current_par_valid) {
-		*par = current_par;
-	} else {
-		fbhw->decode_var(&virgefb_default, par);
-	}
-	DPRINTK("EXIT\n");
-}
-
-
-static void virgefb_set_par(struct virgefb_par *par)
-{
-	DPRINTK("ENTER\n");
-	current_par = *par;
-	current_par_valid = 1;
-	DPRINTK("EXIT\n");
-}
-
-
-static void virgefb_set_video(struct fb_var_screeninfo *var)
-{
-/* Set clipping rectangle to current screen size */
-
-	unsigned int clip;
-
-	DPRINTK("ENTER\n");
-	wait_3d_fifo_slots(4);
-	clip = ((0 << 16) | (var->xres - 1));
-	wl_mmio(BLT_CLIP_LEFT_RIGHT, clip);
-	clip = ((0 << 16) | (var->yres - 1));
-	wl_mmio(BLT_CLIP_TOP_BOTTOM, clip);
-	wl_mmio(BLT_SRC_BASE, 0);		/* seems we need to clear these two */
-	wl_mmio(BLT_DEST_BASE, 0);
-
-/* Load the video mode defined by the 'var' data */
-
-	virgefb_load_video_mode(var);
-	DPRINTK("EXIT\n");
-}
-
-/*
-Merge these two functions, Geert's suggestion.
-static int virgefb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);
-static int virgefb_do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
-*/
-
-static int virgefb_do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
-{
-	int err, activate;
-	struct virgefb_par par;
-
-	DPRINTK("ENTER\n");
-	if ((err = fbhw->decode_var(var, &par))) {
-		DPRINTK("EXIT\n");
-		return (err);
-	}
-
-	activate = var->activate;
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
-		virgefb_set_par(&par);
-	fbhw->encode_var(var, &par);
-	var->activate = activate;
-        if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
-		virgefb_set_video(var);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Get the Fixed Part of the Display
- */
-
-static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			   struct fb_info *info)
-{
-	struct virgefb_par par;
-	int error = 0;
-
-	DPRINTK("ENTER\n");
-	if (con == -1)
-		virgefb_get_par(&par);
-	else
-		error = fbhw->decode_var(&fb_display[con].var, &par);
-
-	if (!error)
-		error = fbhw->encode_fix(fix, &par);
-	DPRINTK("EXIT\n");
-	return(error);
-}
-
-
-/*
- *    Get the User Defined Part of the Display
- */
-
-static int virgefb_get_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	struct virgefb_par par;
-	int error = 0;
-
-	DPRINTK("ENTER\n");
-	if (con == -1) {
-		virgefb_get_par(&par);
-		error = fbhw->encode_var(var, &par);
-		disp.var = *var;   /* ++Andre: don't know if this is the right place */
-	} else {
-		*var = fb_display[con].var;
-	}
-	DPRINTK("EXIT\n");
-	return(error);
-}
-
-static void virgefb_set_disp(int con, struct fb_info *info)
-{
-	struct fb_fix_screeninfo fix;
-	struct display *display;
-
-	DPRINTK("ENTER\n");
-	if (con >= 0)
-		display = &fb_display[con];
-	else
-		display = &disp;	/* used during initialization */
-
-	virgefb_get_fix(&fix, con, info);
-	if (con == -1)
-		con = 0;
-	if(on_zorro2) {
-		info->screen_base = (char*)v_ram;
-	} else {
-	        switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-			case 8:
-				info->screen_base = (char*)(v_ram + CYBMEM_OFFSET_8);
-				break;
-#endif
-#ifdef FBCON_HAS_CFB16
-			case 16:
-				info->screen_base = (char*)(v_ram + CYBMEM_OFFSET_16);
-				break;
-#endif
-#ifdef FBCON_HAS_CFB32
-			case 32:
-				info->screen_base = (char*)(v_ram + CYBMEM_OFFSET_32);
-				break;
-#endif
-		}
-	}
-	display->visual = fix.visual;
-	display->type = fix.type;
-	display->type_aux = fix.type_aux;
-	display->ypanstep = fix.ypanstep;
-	display->ywrapstep = fix.ywrapstep;
-	display->can_soft_blank = 1;
-	display->inverse = virgefb_inverse;
-	display->line_length = display->var.xres_virtual*
-			       display->var.bits_per_pixel/8;
-
-	switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-		case 8:
-			if (display->var.accel_flags & FB_ACCELF_TEXT) {
-		   		display->dispsw = &fbcon_virge8;
-#warning FIXME: We should reinit the graphics engine here
-			} else
-				display->dispsw = &fbcon_cfb8;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16:
-			if (display->var.accel_flags & FB_ACCELF_TEXT) {
-				display->dispsw = &fbcon_virge16;
-			} else
-				display->dispsw = &fbcon_cfb16;
-			display->dispsw_data = &fbcon_cmap.cfb16;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32:
-			if (display->var.accel_flags & FB_ACCELF_TEXT) {
-				display->dispsw = &fbcon_virge32;
-			} else
-				display->dispsw = &fbcon_cfb32;
-			display->dispsw_data = &fbcon_cmap.cfb32;
-			break;
-#endif
-		default:
-			display->dispsw = &fbcon_dummy;
-			break;
-	}
-	DPRINTK("EXIT v_ram virt = 0x%8.8lx\n",(unsigned long)display->screen_base);
-}
-
-
-/*
- *    Set the User Defined Part of the Display
- */
-
-static int virgefb_set_var(struct fb_var_screeninfo *var, int con,
-			   struct fb_info *info)
-{
-	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
-
-	DPRINTK("ENTER\n");
-
-	if ((err = virgefb_do_fb_set_var(var, con == info->currcon))) {
-		DPRINTK("EXIT\n");
-		return(err);
-	}
-	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-		oldxres = fb_display[con].var.xres;
-		oldyres = fb_display[con].var.yres;
-		oldvxres = fb_display[con].var.xres_virtual;
-		oldvyres = fb_display[con].var.yres_virtual;
-		oldbpp = fb_display[con].var.bits_per_pixel;
-		oldaccel = fb_display[con].var.accel_flags;
-		fb_display[con].var = *var;
-		if (oldxres != var->xres || oldyres != var->yres ||
-		    oldvxres != var->xres_virtual ||
-		    oldvyres != var->yres_virtual ||
-		    oldbpp != var->bits_per_pixel ||
-		    oldaccel != var->accel_flags) {
-			virgefb_set_disp(con, info);
-			if (fb_info.changevar)
-				(*fb_info.changevar)(con);
-			fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
-			do_install_cmap(con, info);
-		}
-	}
-	var->activate = 0;
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Get the Colormap
- */
-
-static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			    struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	if (con == info->currcon) { /* current console? */
-		DPRINTK("EXIT - console is current console, fb_get_cmap\n");
-		return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
-	} else if (fb_display[con].cmap.len) { /* non default colormap? */
-		DPRINTK("Use console cmap\n");
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	} else {
-		DPRINTK("Use default cmap\n");
-		fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel==8 ? 256 : 16),
-			     cmap, kspc ? 0 : 2);
-	}
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-static struct fb_ops virgefb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	virgefb_get_fix,
-	.fb_get_var =	virgefb_get_var,
-	.fb_set_var =	virgefb_set_var,
-	.fb_get_cmap =	virgefb_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	virgefb_setcolreg,
-	.fb_blank =	virgefb_blank,
-};
-
-int __init virgefb_setup(char *options)
-{
-	char *this_opt;
-	fb_info.fontname[0] = '\0';
-
-	DPRINTK("ENTER\n");
-	if (!options || !*options) {
-		DPRINTK("EXIT\n");
-		return 0;
-	}
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!*this_opt)
-			continue;
-		if (!strcmp(this_opt, "inverse")) {
-			virgefb_inverse = 1;
-			fb_invert_cmaps();
-		} else if (!strncmp(this_opt, "font:", 5))
-			strcpy(fb_info.fontname, this_opt+5);
-#ifdef FBCON_HAS_CFB8
-		else if (!strcmp (this_opt, "virge8")){
-			virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var;
-		}
-#endif
-#ifdef FBCON_HAS_CFB16
-		else if (!strcmp (this_opt, "virge16")){
-			virgefb_default = virgefb_predefined[VIRGE16_DEFMODE].var;
-		}
-#endif
-#ifdef FBCON_HAS_CFB32
-		else if (!strcmp (this_opt, "virge32")){
-			virgefb_default = virgefb_predefined[VIRGE32_DEFMODE].var;
-		}
-#endif
-		else
-			virgefb_get_video_mode(this_opt);
-	}
-
-	printk(KERN_INFO "mode : xres=%d, yres=%d, bpp=%d\n", virgefb_default.xres,
-			virgefb_default.yres, virgefb_default.bits_per_pixel);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Get a Video Mode
- */
-
-static int __init virgefb_get_video_mode(const char *name)
-{
-	int i;
-
-	DPRINTK("ENTER\n");
-	for (i = 0; i < NUM_TOTAL_MODES; i++) {
-		if (!strcmp(name, virgefb_predefined[i].name)) {
-			virgefb_default = virgefb_predefined[i].var;
-			DPRINTK("EXIT\n");
-			return(i);
-		}
-	}
-	/* ++Andre: set virgefb default mode */
-
-/* prefer 16 bit depth, 8 if no 16, if no 8 or 16 use 32 */
-
-#ifdef FBCON_HAS_CFB32
-	virgefb_default = virgefb_predefined[VIRGE32_DEFMODE].var;
-#endif
-#ifdef FBCON_HAS_CFB8
-	virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var;
-#endif
-#ifdef FBCON_HAS_CFB16
-	virgefb_default = virgefb_predefined[VIRGE16_DEFMODE].var;
-#endif
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-/*
- *    Initialization
- */
-
-int __init virgefb_init(void)
-{
-	struct virgefb_par par;
-	unsigned long board_addr, board_size;
-	struct zorro_dev *z = NULL;
-
-	DPRINTK("ENTER\n");
-
-	z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64_3D, NULL);
-	if (!z)
-		return -ENODEV;
-
-	board_addr = z->resource.start;
-	if (board_addr < 0x01000000) {
-
-		/* board running in Z2 space. This includes the video memory
-		    as well as the S3 register set */
-
-		on_zorro2 = 1;
-		board_size = 0x00400000;
-
-		if (!request_mem_region(board_addr, board_size, "S3 ViRGE"))
-			return -ENOMEM;
-
-		v_ram_phys = board_addr;
-		v_ram = ZTWO_VADDR(v_ram_phys);
-		mmio_regs_phys = (unsigned long)(board_addr + 0x003c0000);
-		vgaio_regs = (unsigned char *) ZTWO_VADDR(board_addr + 0x003c0000);
-		mmio_regs = (unsigned char *)ZTWO_VADDR(mmio_regs_phys);
-		vcode_switch_base = (unsigned long) ZTWO_VADDR(board_addr + 0x003a0000);
-		printk(KERN_INFO "CV3D detected running in Z2 mode.\n");
-
-	} else {
-
-		/* board running in Z3 space. Separate video memory (3 apertures)
-		   and S3 register set */
-
-		on_zorro2 = 0;
-		board_size = 0x01000000;
-
-		if (!request_mem_region(board_addr, board_size, "S3 ViRGE"))
-			return -ENOMEM;
-
-		v_ram_phys  = board_addr + 0x04000000;
-		v_ram = (unsigned long)ioremap(v_ram_phys, 0x01000000);
-		mmio_regs_phys = board_addr + 0x05000000;
-		vgaio_regs = (unsigned char *)ioremap(board_addr +0x0c000000, 0x00100000); /* includes PCI regs */
-		mmio_regs = ioremap(mmio_regs_phys, 0x00010000);
-		vcode_switch_base = (unsigned long)ioremap(board_addr + 0x08000000, 0x1000);
-		printk(KERN_INFO "CV3D detected running in Z3 mode\n");
-	}
-
-#if defined (VIRGEFBDEBUG)
-	DPRINTK("board_addr     : 0x%8.8lx\n",board_addr);
-	DPRINTK("board_size     : 0x%8.8lx\n",board_size);
-	DPRINTK("mmio_regs_phy  : 0x%8.8lx\n",mmio_regs_phys);
-	DPRINTK("v_ram_phys     : 0x%8.8lx\n",v_ram_phys);
-	DPRINTK("vgaio_regs     : 0x%8.8lx\n",(unsigned long)vgaio_regs);
-	DPRINTK("mmio_regs      : 0x%8.8lx\n",(unsigned long)mmio_regs);
-	DPRINTK("v_ram          : 0x%8.8lx\n",v_ram);
-	DPRINTK("vcode sw base  : 0x%8.8lx\n",vcode_switch_base);
-#endif
-	fbhw = &virgefb_hw_switch;
-	strcpy(fb_info.modename, virgefb_name);
-	fb_info.changevar = NULL;
-	fb_info.fbops = &virgefb_ops;
-	fb_info.disp = &disp;
-	fb_info.currcon = -1;
-	fb_info.switch_con = &virgefb_switch;
-	fb_info.updatevar = &virgefb_updatevar;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
-	fbhw->init();
-	fbhw->decode_var(&virgefb_default, &par);
-	fbhw->encode_var(&virgefb_default, &par);
-	virgefb_do_fb_set_var(&virgefb_default, 1);
-	virgefb_get_var(&fb_display[0].var, -1, &fb_info);
-	virgefb_set_disp(-1, &fb_info);
-	do_install_cmap(0, &fb_info);
-
-	if (register_framebuffer(&fb_info) < 0) {
-		#warning release resources
-		printk(KERN_ERR "virgefb.c: register_framebuffer failed\n");
-		DPRINTK("EXIT\n");
-		goto out_unmap;
-	}
-
-	printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of video memory\n",
-	       fb_info.node, fb_info.modename, v_ram_size>>10);
-
-	/* TODO: This driver cannot be unloaded yet */
-
-	DPRINTK("EXIT\n");
-	return 0;
-
-out_unmap:
-	if (board_addr >= 0x01000000) {
-		if (v_ram)
-			iounmap((void*)v_ram);
-		if (vgaio_regs)
-			iounmap(vgaio_regs);
-		if (mmio_regs)
-			iounmap(mmio_regs);
-		if (vcode_switch_base)
-			iounmap((void*)vcode_switch_base);
-		v_ram = vcode_switch_base = 0;
-		vgaio_regs = mmio_regs = NULL;
-	}
-	return -EINVAL;
-}
-
-
-static int virgefb_switch(int con, struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	/* Do we have to save the colormap? */
-	if (fb_display[info->currcon].cmap.len)
-		fb_get_cmap(&fb_display[info->currcon].cmap, 1,
-			    fbhw->getcolreg, info);
-	virgefb_do_fb_set_var(&fb_display[con].var, 1);
-	info->currcon = con;
-	/* Install new colormap */
-	do_install_cmap(con, info);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Update the `var' structure (called by fbcon.c)
- *
- *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
- *    Since it's called by a kernel driver, no range checking is done.
- */
-
-static int virgefb_updatevar(int con, struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	return 0;
-	DPRINTK("EXIT\n");
-}
-
-/*
- *    Blank the display.
- */
-
-static int virgefb_blank(int blank, struct fb_info *info)
-{
-	DPRINTK("ENTER\n");
-	fbhw->blank(blank);
-	DPRINTK("EXIT\n");
-	return 0;
-}
-
-
-/*
- *    Text console acceleration
- */
-
-#ifdef FBCON_HAS_CFB8
-static void fbcon_virge8_bmove(struct display *p, int sy, int sx, int dy,
-			       int dx, int height, int width)
-{
-        sx *= 8; dx *= 8; width *= 8;
-        virgefb_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-                       (u_short)(dy*fontheight(p)), (u_short)width,
-                       (u_short)(height*fontheight(p)), (u_short)p->next_line, 8);
-}
-
-static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
-			       int sx, int height, int width)
-{
-        unsigned char bg;
-
-        sx *= 8; width *= 8;
-        bg = attr_bgcol_ec(p,conp);
-        virgefb_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
-                         (u_short)width, (u_short)(height*fontheight(p)),
-                         (u_short)bg, (u_short)p->next_line, 8);
-}
-
-static void fbcon_virge8_putc(struct vc_data *conp, struct display *p, int c, int yy,
-                              int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb8_putc(conp, p, c, yy, xx);
-}
-
-static void fbcon_virge8_putcs(struct vc_data *conp, struct display *p,
-                      const unsigned short *s, int count, int yy, int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
-}
-
-static void fbcon_virge8_revc(struct display *p, int xx, int yy)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb8_revc(p, xx, yy);
-}
-
-static void fbcon_virge8_clear_margins(struct vc_data *conp, struct display *p,
-                              int bottom_only)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb8_clear_margins(conp, p, bottom_only);
-}
-
-static struct display_switch fbcon_virge8 = {
-	.setup		= fbcon_cfb8_setup,
-	.bmove		= fbcon_virge8_bmove,
-	.clear		= fbcon_virge8_clear,
-	.putc		= fbcon_virge8_putc,
-	.putcs		= fbcon_virge8_putcs,
-	.revc		= fbcon_virge8_revc,
-	.clear_margins	= fbcon_virge8_clear_margins,
-	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-
-#ifdef FBCON_HAS_CFB16
-static void fbcon_virge16_bmove(struct display *p, int sy, int sx, int dy,
-                               int dx, int height, int width)
-{
-        sx *= 8; dx *= 8; width *= 8;
-        virgefb_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-                       (u_short)(dy*fontheight(p)), (u_short)width,
-                       (u_short)(height*fontheight(p)), (u_short)p->next_line, 16);
-}
-
-static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy,
-                               int sx, int height, int width)
-{
-        unsigned char bg;
-
-        sx *= 8; width *= 8;
-        bg = attr_bgcol_ec(p,conp);
-        virgefb_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
-                         (u_short)width, (u_short)(height*fontheight(p)),
-                         (u_short)bg, (u_short)p->next_line, 16);
-}
-
-static void fbcon_virge16_putc(struct vc_data *conp, struct display *p, int c, int yy,
-                              int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb16_putc(conp, p, c, yy, xx);
-}
-
-static void fbcon_virge16_putcs(struct vc_data *conp, struct display *p,
-                      const unsigned short *s, int count, int yy, int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
-}
-
-static void fbcon_virge16_revc(struct display *p, int xx, int yy)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb16_revc(p, xx, yy);
-}
-
-static void fbcon_virge16_clear_margins(struct vc_data *conp, struct display *p,
-                              int bottom_only)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb16_clear_margins(conp, p, bottom_only);
-}
-
-static struct display_switch fbcon_virge16 = {
-	.setup		= fbcon_cfb16_setup,
-	.bmove		= fbcon_virge16_bmove,
-	.clear		= fbcon_virge16_clear,
-	.putc		= fbcon_virge16_putc,
-	.putcs		= fbcon_virge16_putcs,
-	.revc		= fbcon_virge16_revc,
-	.clear_margins	= fbcon_virge16_clear_margins,
-	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-
-#ifdef FBCON_HAS_CFB32
-static void fbcon_virge32_bmove(struct display *p, int sy, int sx, int dy,
-			       int dx, int height, int width)
-{
-        sx *= 16; dx *= 16; width *= 16;	/* doubled these values to do 32 bit blit */
-        virgefb_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
-                       (u_short)(dy*fontheight(p)), (u_short)width,
-                       (u_short)(height*fontheight(p)), (u_short)p->next_line, 16);
-}
-
-static void fbcon_virge32_clear(struct vc_data *conp, struct display *p, int sy,
-			       int sx, int height, int width)
-{
-        unsigned char bg;
-
-        sx *= 16; width *= 16;			/* doubled these values to do 32 bit blit */
-        bg = attr_bgcol_ec(p,conp);
-        virgefb_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
-                         (u_short)width, (u_short)(height*fontheight(p)),
-                         (u_short)bg, (u_short)p->next_line, 16);
-}
-
-static void fbcon_virge32_putc(struct vc_data *conp, struct display *p, int c, int yy,
-                              int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb32_putc(conp, p, c, yy, xx);
-}
-
-static void fbcon_virge32_putcs(struct vc_data *conp, struct display *p,
-                      const unsigned short *s, int count, int yy, int xx)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
-}
-
-static void fbcon_virge32_revc(struct display *p, int xx, int yy)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb32_revc(p, xx, yy);
-}
-
-static void fbcon_virge32_clear_margins(struct vc_data *conp, struct display *p,
-                              int bottom_only)
-{
-	if (blit_maybe_busy)
-		virgefb_wait_for_idle();
-	fbcon_cfb32_clear_margins(conp, p, bottom_only);
-}
-
-static struct display_switch fbcon_virge32 = {
-	.setup		= fbcon_cfb32_setup,
-	.bmove		= fbcon_virge32_bmove,
-	.clear		= fbcon_virge32_clear,
-	.putc		= fbcon_virge32_putc,
-	.putcs		= fbcon_virge32_putcs,
-	.revc		= fbcon_virge32_revc,
-	.clear_margins	= fbcon_virge32_clear_margins,
-	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-
-#ifdef MODULE
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	return virgefb_init();
-}
-#endif /* MODULE */
-
-static int cv3d_has_4mb(void)
-{
-	/* cyberfb version didn't work, neither does this (not reliably)
-	forced to return 4MB */
-#if 0
-	volatile unsigned long *t0, *t2;
-#endif
-	DPRINTK("ENTER\n");
-#if 0
-	/* write patterns in memory and test if they can be read */
-	t0 = (volatile unsigned long *)v_ram;
-	t2 = (volatile unsigned long *)(v_ram + 0x00200000);
-	*t0 = 0x87654321;
-	*t2 = 0x12345678;
-
-	if (*t0 != 0x87654321) {
-		/* read of first location failed */
-		DPRINTK("EXIT - 0MB !\n");
-		return 0;
-	}
-
-	if (*t2 == 0x87654321) {
-		/* should read 0x12345678 if 4MB */
-		DPRINTK("EXIT - 2MB(a) \n");
-		return 0;
-	}
-
-	if (*t2 != 0x12345678) {
-		/* upper 2MB read back match failed */
-		DPRINTK("EXIT - 2MB(b)\n");
-		return 0;
-	}
-
-	/* may have 4MB */
-
-	*t2 = 0xAAAAAAAA;
-
-	if(*t2 != 0xAAAAAAAA) {
-		/* upper 2MB read back match failed */
-		DPRINTK("EXIT - 2MB(c)\n");
-		return 0;
-	}
-
-	*t2 = 0x55555555;
-
-	if(*t2 != 0x55555555) {
-		/* upper 2MB read back match failed */
-		DPRINTK("EXIT - 2MB(d)\n");
-		return 0;
-	}
-
-#endif
-	DPRINTK("EXIT - 4MB\n");
-	return 1;
-}
-
-
-/*
- * Computes M, N, and R pll params for freq arg.
- * Returns 16 bits - hi 0MMMMMM lo 0RRNNNNN
- */
-
-#define REFCLOCK 14318000
-
-static unsigned short virgefb_compute_clock(unsigned long freq)
-{
-
-	unsigned char m, n, r, rpwr;
-	unsigned long diff, ftry, save = ~0UL;
-	unsigned short mnr;
-
-	DPRINTK("ENTER\n");
-
-	for (r = 0, rpwr = 1 ; r < 4 ; r++, rpwr *= 2) {
-		if ((135000000 <= (rpwr * freq)) && ((rpwr * freq) <= 270000000)) {
-			for (n = 1 ; n < 32 ; n++) {
-				m = ((freq * (n + 2) * rpwr)/REFCLOCK) - 2;
-				if (m == 0 || m >127)
-					break;
-				ftry = ((REFCLOCK / (n + 2)) * (m + 2)) / rpwr;
-				if (ftry > freq)
-					diff = ftry - freq;
-				else
-					diff = freq - ftry;
-				if (diff < save) {
-					save = diff;
-					mnr =  (m << 8) | (r<<5) | (n & 0x7f);
-				}
-			}
-		}
-	}
-	if (save == ~0UL)
-		printk("Can't compute clock PLL values for %ld Hz clock\n", freq);
-	DPRINTK("EXIT\n");
-	return(mnr);
-}
-
-static void virgefb_load_video_mode(struct fb_var_screeninfo *video_mode)
-{
-	unsigned char lace, dblscan, tmp;
-	unsigned short mnr;
-	unsigned short HT, HDE, HBS, HBW, HSS, HSW;
-	unsigned short VT, VDE, VBS, VBW, VSS, VSW;
-	unsigned short SCO;
-	int cr11;
-	int cr67;
-	int hmul;
-	int xres, xres_virtual, hfront, hsync, hback;
-	int yres, vfront, vsync, vback;
-	int bpp;
-	int i;
-	long freq;
-
-	DPRINTK("ENTER : %dx%d-%d\n",video_mode->xres, video_mode->yres,
-				video_mode->bits_per_pixel);
-
-	bpp = video_mode->bits_per_pixel;
-	xres = video_mode->xres;
-	xres_virtual = video_mode->xres_virtual;
-	hfront = video_mode->right_margin;
-	hsync = video_mode->hsync_len;
-	hback = video_mode->left_margin;
-
-	lace = 0;
-	dblscan = 0;
-
-	if (video_mode->vmode & FB_VMODE_DOUBLE) {
-		yres = video_mode->yres * 2;
-		vfront = video_mode->lower_margin * 2;
-		vsync = video_mode->vsync_len * 2;
-		vback = video_mode->upper_margin * 2;
-		dblscan = 1;
-	} else if (video_mode->vmode & FB_VMODE_INTERLACED) {
-		yres = (video_mode->yres + 1) / 2;
-		vfront = (video_mode->lower_margin + 1) / 2;
-		vsync = (video_mode->vsync_len + 1) / 2;
-		vback = (video_mode->upper_margin + 1) / 2;
-		lace = 1;
-	} else {
-		yres = video_mode->yres;
-		vfront = video_mode->lower_margin;
-		vsync = video_mode->vsync_len;
-		vback = video_mode->upper_margin;
-	}
-
-	switch (bpp) {
-		case 8:
-			video_mode->red.offset = 0;
-			video_mode->green.offset = 0;
-			video_mode->blue.offset = 0;
-			video_mode->transp.offset = 0;
-			video_mode->red.length = 8;
-			video_mode->green.length = 8;
-			video_mode->blue.length = 8;
-			video_mode->transp.length = 0;
-			hmul = 1;
-			cr67 = 0x00;
-			SCO = xres_virtual / 8;
-			break;
-		case 16:
-			video_mode->red.offset = 11;
-			video_mode->green.offset = 5;
-			video_mode->blue.offset = 0;
-			video_mode->transp.offset = 0;
-			video_mode->red.length = 5;
-			video_mode->green.length = 6;
-			video_mode->blue.length = 5;
-			video_mode->transp.length = 0;
-			hmul = 2;
-			cr67 = 0x50;
-			SCO = xres_virtual / 4;
-			break;
-		case 32:
-			video_mode->red.offset = 16;
-			video_mode->green.offset = 8;
-			video_mode->blue.offset = 0;
-			video_mode->transp.offset = 24;
-			video_mode->red.length = 8;
-			video_mode->green.length = 8;
-			video_mode->blue.length = 8;
-			video_mode->transp.length = 8;
-			hmul = 1;
-			cr67 = 0xd0;
-			SCO = xres_virtual / 2;
-			break;
-	}
-
-	HT  = (((xres + hfront + hsync + hback) / 8) * hmul) - 5;
-	HDE = ((xres / 8) * hmul) - 1;
-	HBS = (xres / 8) * hmul;
-	HSS = ((xres + hfront) / 8) * hmul;
-	HSW = (hsync / 8) * hmul;
-	HBW = (((hfront + hsync + hback) / 8) * hmul) - 2;
-
-	VT  = yres + vfront + vsync + vback - 2;
-	VDE = yres - 1;
-	VBS = yres - 1;
-	VSS = yres + vfront;
-	VSW = vsync;
-	VBW = vfront + vsync + vback - 2;
-
-#ifdef VIRGEFBDEBUG
-	DPRINTK("HDE       : 0x%4.4x, %4.4d\n", HDE, HDE);
-	DPRINTK("HBS       : 0x%4.4x, %4.4d\n", HBS, HBS);
-	DPRINTK("HSS       : 0x%4.4x, %4.4d\n", HSS, HSS);
-	DPRINTK("HSW       : 0x%4.4x, %4.4d\n", HSW, HSW);
-	DPRINTK("HBW       : 0x%4.4x, %4.4d\n", HBW, HBW);
-	DPRINTK("HSS + HSW : 0x%4.4x, %4.4d\n", HSS+HSW, HSS+HSW);
-	DPRINTK("HBS + HBW : 0x%4.4x, %4.4d\n", HBS+HBW, HBS+HBW);
-	DPRINTK("HT        : 0x%4.4x, %4.4d\n", HT, HT);
-	DPRINTK("VDE       : 0x%4.4x, %4.4d\n", VDE, VDE);
-	DPRINTK("VBS       : 0x%4.4x, %4.4d\n", VBS, VBS);
-	DPRINTK("VSS       : 0x%4.4x, %4.4d\n", VSS, VSS);
-	DPRINTK("VSW       : 0x%4.4x, %4.4d\n", VSW, VSW);
-	DPRINTK("VBW       : 0x%4.4x, %4.4d\n", VBW, VBW);
-	DPRINTK("VT        : 0x%4.4x, %4.4d\n", VT, VT);
-#endif
-
-/* turn gfx off, don't mess up the display */
-
- 	gfx_on_off(1);
-
-/* H and V sync polarity */
-
-	tmp = rb_mmio(GREG_MISC_OUTPUT_R) & 0x2f;		/* colour, ram enable, clk sr12/s13 sel */
-	if (!(video_mode->sync & FB_SYNC_HOR_HIGH_ACT))
-		tmp |= 0x40;					/* neg H sync polarity */
-	if (!(video_mode->sync & FB_SYNC_VERT_HIGH_ACT))
-		tmp |= 0x80;					/* neg V sync polarity */
-	tmp |= 0x0c;						/* clk from sr12/sr13 */
-	wb_mmio(GREG_MISC_OUTPUT_W, tmp);
-
-/* clocks */
-
-	wseq(SEQ_ID_BUS_REQ_CNTL, 0xc0);			/* 2 clk mem wr and /RAS1 */
-	wseq(SEQ_ID_CLKSYN_CNTL_2, 0x80);			/* b7 is 2 mem clk wr */
-	mnr = virgefb_compute_clock(MEMCLOCK);
-	DPRINTK("mem clock %d, m %d, n %d, r %d.\n", MEMCLOCK, ((mnr>>8)&0x7f), (mnr&0x1f), ((mnr >> 5)&0x03));
-	wseq(SEQ_ID_MCLK_LO, (mnr & 0x7f));
-	wseq(SEQ_ID_MCLK_HI, ((mnr & 0x7f00) >> 8));
-	freq = (1000000000 / video_mode->pixclock) * 1000;	/* pixclock is in ps ... convert to Hz */
-	mnr = virgefb_compute_clock(freq);
-	DPRINTK("dot clock %ld, m %d, n %d, r %d.\n", freq, ((mnr>>8)&0x7f), (mnr&0x1f), ((mnr>>5)&0x03));
-	wseq(SEQ_ID_DCLK_LO, (mnr & 0x7f));
-	wseq(SEQ_ID_DCLK_HI, ((mnr & 0x7f00) >> 8));
-	wseq(SEQ_ID_CLKSYN_CNTL_2, 0xa0);
-	wseq(SEQ_ID_CLKSYN_CNTL_2, 0x80);
-	udelay(100);
-
-/* load display parameters into board */
-
-	/* not sure about sync and blanking extensions bits in cr5d and cr5 */
-
-	wcrt(CRT_ID_EXT_HOR_OVF,			/* 0x5d */
-		((HT & 0x100) ?         0x01 : 0x00) |
-		((HDE & 0x100) ?        0x02 : 0x00) |
-		((HBS & 0x100) ?        0x04 : 0x00) |
-	/*	(((HBS + HBW) & 0x40) ? 0x08 : 0x00) |	*/
-		((HSS & 0x100) ?        0x10 : 0x00) |
-	/*	(((HSS + HSW) & 0x20) ? 0x20 : 0x00) |	*/
-		((HSW >= 0x20) ?        0x20 : 0x00) |
-		(((HT-5) & 0x100) ?     0x40 : 0x00));
-
-	wcrt(CRT_ID_EXT_VER_OVF,			/* 0x5e */
-		((VT & 0x400) ? 0x01 : 0x00) |
-		((VDE & 0x400) ? 0x02 : 0x00) |
-		((VBS & 0x400) ? 0x04 : 0x00) |
-		((VSS & 0x400) ? 0x10 : 0x00) |
-		0x40);					/* line compare */
-
-	wcrt(CRT_ID_START_VER_RETR, VSS);
-	cr11 = rcrt(CRT_ID_END_VER_RETR) | 0x20;	/* vert interrupt flag */
-	wcrt(CRT_ID_END_VER_RETR, ((cr11 & 0x20) | ((VSS + VSW) & 0x0f)));	/* keeps vert irq enable state, also has unlock bit cr0 to 7 */
-	wcrt(CRT_ID_VER_DISP_ENA_END, VDE);
-	wcrt(CRT_ID_START_VER_BLANK, VBS);
-	wcrt(CRT_ID_END_VER_BLANK, VBS + VBW);		/* might be +/- 1 out */
-	wcrt(CRT_ID_HOR_TOTAL, HT);
-	wcrt(CRT_ID_DISPLAY_FIFO, HT - 5);
-	wcrt(CRT_ID_BACKWAD_COMP_3, 0x10);		/* enable display fifo */
-	wcrt(CRT_ID_HOR_DISP_ENA_END, HDE);
-	wcrt(CRT_ID_START_HOR_BLANK , HBS);
-	wcrt(CRT_ID_END_HOR_BLANK, (HBS + HBW) & 0x1f);
-	wcrt(CRT_ID_START_HOR_RETR, HSS);
-	wcrt(CRT_ID_END_HOR_RETR,			/* cr5 */
-		((HSS + HSW) & 0x1f) |
-		(((HBS + HBW) & 0x20) ? 0x80 : 0x00));
-	wcrt(CRT_ID_VER_TOTAL, VT);
-	wcrt(CRT_ID_OVERFLOW,
-		((VT & 0x100) ? 0x01 : 0x00) |
-		((VDE & 0x100) ? 0x02 : 0x00) |
-		((VSS & 0x100) ? 0x04 : 0x00) |
-		((VBS & 0x100) ? 0x08 : 0x00) |
-		0x10 |
-		((VT & 0x200) ? 0x20 : 0x00) |
-		((VDE & 0x200) ? 0x40 : 0x00) |
-		((VSS & 0x200) ? 0x80 : 0x00));
-	wcrt(CRT_ID_MAX_SCAN_LINE,
-		(dblscan ? 0x80 : 0x00) |
-		0x40 |
-		((VBS & 0x200) ? 0x20 : 0x00));
-	wcrt(CRT_ID_LINE_COMPARE, 0xff);
-	wcrt(CRT_ID_LACE_RETR_START, HT / 2);		/* (HT-5)/2 ? */
-	wcrt(CRT_ID_LACE_CONTROL, (lace ? 0x20 : 0x00));
-
-	wcrt(CRT_ID_SCREEN_OFFSET, SCO);
-	wcrt(CRT_ID_EXT_SYS_CNTL_2, (SCO >> 4) & 0x30 );
-
-	/* wait for vert sync before cr67 update */
-
-	for (i=0; i < 10000; i++) {
-		udelay(10);
-		mb();
-		if (rb_mmio(GREG_INPUT_STATUS1_R) & 0x08)
-			break;
-	}
-
-	wl_mmio(0x8200, 0x0000c000);	/* fifo control  (0x00110400 ?) */
-	wcrt(CRT_ID_EXT_MISC_CNTL_2, cr67);
-
-/* enable video */
-
-	tmp = rb_mmio(ACT_ADDRESS_RESET);
-	wb_mmio(ACT_ADDRESS_W, ((bpp == 8) ? 0x20 : 0x00));	/* set b5, ENB PLT in attr idx reg) */
-	tmp = rb_mmio(ACT_ADDRESS_RESET);
-
-/* turn gfx on again */
-
-	gfx_on_off(0);
-
-/* pass-through */
-
-	SetVSwitch(1);		/* cv3d */
-
-	DUMP;
-	DPRINTK("EXIT\n");
-}
-
-static inline void gfx_on_off(int toggle)
-{
-	unsigned char tmp;
-
-	DPRINTK("ENTER gfx %s\n", (toggle ? "off" : "on"));
-
-	toggle = (toggle & 0x01) << 5;
-	tmp = rseq(SEQ_ID_CLOCKING_MODE) & (~(0x01 << 5));
-	wseq(SEQ_ID_CLOCKING_MODE, tmp | toggle);
-
-	DPRINTK("EXIT\n");
-}
-
-#if defined (VIRGEFBDUMP)
-
-/*
- * Dump board registers
- */
-
-static void cv64_dump(void)
-{
-	int i;
-	u8 c, b;
-        u16 w;
-	u32 l;
-
-	/* crt, seq, gfx and atr regs */
-
-	SelectMMIO;
-
-	printk("\n");
-	for (i = 0; i <= 0x6f; i++) {
-		wb_mmio(CRT_ADDRESS, i);
-		printk("crt idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(CRT_ADDRESS_R));
-	}
-	for (i = 0; i <= 0x1c; i++) {
-		wb_mmio(SEQ_ADDRESS, i);
-		printk("seq idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(SEQ_ADDRESS_R));
-	}
-	for (i = 0; i <= 8; i++) {
-		wb_mmio(GCT_ADDRESS, i);
-		printk("gfx idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(GCT_ADDRESS_R));
-	}
-	for (i = 0; i <= 0x14; i++) {
-		c = rb_mmio(ACT_ADDRESS_RESET);
-		wb_mmio(ACT_ADDRESS_W, i);
-		printk("atr idx : 0x%2.2x : 0x%2.2x\n", i, rb_mmio(ACT_ADDRESS_R));
-	}
-
-	/* re-enable video access to palette */
-
-	c = rb_mmio(ACT_ADDRESS_RESET);
-	udelay(10);
-	wb_mmio(ACT_ADDRESS_W, 0x20);
-	c = rb_mmio(ACT_ADDRESS_RESET);
-	udelay(10);
-
-	/* general regs */
-
-	printk("0x3cc(w 0x3c2) : 0x%2.2x\n", rb_mmio(0x3cc));	/* GREG_MISC_OUTPUT READ */
-	printk("0x3c2(-------) : 0x%2.2x\n", rb_mmio(0x3c2));	/* GREG_INPUT_STATUS 0 READ */
-	printk("0x3c3(w 0x3c3) : 0x%2.2x\n", rb_vgaio(0x3c3));	/* GREG_VIDEO_SUBS_ENABLE */
-	printk("0x3ca(w 0x3da) : 0x%2.2x\n", rb_vgaio(0x3ca));	/* GREG_FEATURE_CONTROL read */
-	printk("0x3da(-------) : 0x%2.2x\n", rb_mmio(0x3da));	/* GREG_INPUT_STATUS 1 READ */
-
-	/* engine regs */
-
-	for (i = 0x8180; i <= 0x8200; i = i + 4)
-		printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
-
-	i = 0x8504;
-	printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
-	i = 0x850c;
-	printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
-	for (i = 0xa4d4; i <= 0xa50c; i = i + 4)
-		printk("0x%8.8x : 0x%8.8x\n", i, rl_mmio(i));
-
-	/* PCI regs */
-
-	SelectCFG;
-
-	for (c = 0; c < 0x08; c = c + 2) {
-		w = (*((u16 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 2)));
-		printk("pci 0x%2.2x : 0x%4.4x\n", c, w);
-	}
-	c = 8;
-	l = (*((u32 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)))));
-	printk("pci 0x%2.2x : 0x%8.8x\n", c, l);
-	c = 0x0d;
-	b = (*((u8 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 3)));
-	printk("pci 0x%2.2x : 0x%2.2x\n", c, b);
-	c = 0x10;
-	l = (*((u32 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)))));
-	printk("pci 0x%2.2x : 0x%8.8x\n", c, l);
-	c = 0x30;
-	l = (*((u32 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)))));
-	printk("pci 0x%2.2x : 0x%8.8x\n", c, l);
-	c = 0x3c;
-	b = (*((u8 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 3)));
-	printk("pci 0x%2.2x : 0x%2.2x\n", c, b);
-	c = 0x3d;
-	b = (*((u8 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 3)));
-	printk("pci 0x%2.2x : 0x%2.2x\n", c, b);
-	c = 0x3e;
-	w = (*((u16 *)((u32)(vgaio_regs + c + (on_zorro2 ? 0 : 0x000e0000)) ^ 2)));
-	printk("pci 0x%2.2x : 0x%4.4x\n", c, w);
-	SelectMMIO;
-}
-#endif
diff --git a/drivers/video/virgefb.h b/drivers/video/virgefb.h
deleted file mode 100644
index 157d66d..0000000
--- a/drivers/video/virgefb.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * linux/drivers/video/virgefb.h -- CyberVision64 definitions for the
- *                                  text console driver.
- *
- *   Copyright (c) 1998 Alan Bair
- *
- * This file is based on the initial port to Linux of grf_cvreg.h:
- *
- *   Copyright (c) 1997 Antonio Santos
- *
- * The original work is from the NetBSD CyberVision 64 framebuffer driver 
- * and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
- * Permission to use the source of this driver was obtained from the
- * author Michael Teske by Alan Bair.
- *
- *   Copyright (c) 1995 Michael Teske
- *
- * History:
- *
- *
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/* Enhanced register mapping (MMIO mode) */
-
-#define S3_CRTC_ADR    0x03d4
-#define S3_CRTC_DATA   0x03d5
-
-#define S3_REG_LOCK2	0x39
-#define S3_HGC_MODE	0x45
-
-#define S3_HWGC_ORGX_H	0x46
-#define S3_HWGC_ORGX_L	0x47
-#define S3_HWGC_ORGY_H	0x48
-#define S3_HWGC_ORGY_L	0x49
-#define S3_HWGC_DX	0x4e
-#define S3_HWGC_DY	0x4f
-
-#define S3_LAW_CTL	0x58
-
-/**************************************************/
-
-/*
- * Defines for the used register addresses (mw)
- *
- * NOTE: There are some registers that have different addresses when
- *       in mono or color mode. We only support color mode, and thus
- *       some addresses won't work in mono-mode!
- *
- * General and VGA-registers taken from retina driver. Fixed a few
- * bugs in it. (SR and GR read address is Port + 1, NOT Port)
- *
- */
-
-/* General Registers: */
-#define GREG_MISC_OUTPUT_R	0x03CC
-#define GREG_MISC_OUTPUT_W	0x03C2	
-#define GREG_FEATURE_CONTROL_R	0x03CA 
-#define GREG_FEATURE_CONTROL_W	0x03DA
-#define GREG_INPUT_STATUS0_R	0x03C2
-#define GREG_INPUT_STATUS1_R	0x03DA
-
-/* Setup Registers: */
-#define SREG_VIDEO_SUBS_ENABLE	0x03C3	/* virge */
-
-/* Attribute Controller: */
-#define ACT_ADDRESS		0x03C0
-#define ACT_ADDRESS_R		0x03C1
-#define ACT_ADDRESS_W		0x03C0
-#define ACT_ADDRESS_RESET	0x03DA
-#define ACT_ID_PALETTE0		0x00
-#define ACT_ID_PALETTE1		0x01
-#define ACT_ID_PALETTE2		0x02
-#define ACT_ID_PALETTE3		0x03
-#define ACT_ID_PALETTE4		0x04
-#define ACT_ID_PALETTE5		0x05
-#define ACT_ID_PALETTE6		0x06
-#define ACT_ID_PALETTE7		0x07
-#define ACT_ID_PALETTE8		0x08
-#define ACT_ID_PALETTE9		0x09
-#define ACT_ID_PALETTE10	0x0A
-#define ACT_ID_PALETTE11	0x0B
-#define ACT_ID_PALETTE12	0x0C
-#define ACT_ID_PALETTE13	0x0D
-#define ACT_ID_PALETTE14	0x0E
-#define ACT_ID_PALETTE15	0x0F
-#define ACT_ID_ATTR_MODE_CNTL	0x10
-#define ACT_ID_OVERSCAN_COLOR	0x11
-#define ACT_ID_COLOR_PLANE_ENA	0x12
-#define ACT_ID_HOR_PEL_PANNING	0x13
-#define ACT_ID_COLOR_SELECT	0x14    /* virge PX_PADD  pixel padding register */
-
-/* Graphics Controller: */
-#define GCT_ADDRESS		0x03CE
-#define GCT_ADDRESS_R		0x03CF
-#define GCT_ADDRESS_W		0x03CF
-#define GCT_ID_SET_RESET	0x00
-#define GCT_ID_ENABLE_SET_RESET	0x01
-#define GCT_ID_COLOR_COMPARE	0x02
-#define GCT_ID_DATA_ROTATE	0x03
-#define GCT_ID_READ_MAP_SELECT	0x04
-#define GCT_ID_GRAPHICS_MODE	0x05
-#define GCT_ID_MISC		0x06
-#define GCT_ID_COLOR_XCARE	0x07
-#define GCT_ID_BITMASK		0x08
-
-/* Sequencer: */
-#define SEQ_ADDRESS		0x03C4
-#define SEQ_ADDRESS_R		0x03C5
-#define SEQ_ADDRESS_W		0x03C5
-#define SEQ_ID_RESET		0x00
-#define SEQ_ID_CLOCKING_MODE	0x01
-#define SEQ_ID_MAP_MASK		0x02
-#define SEQ_ID_CHAR_MAP_SELECT	0x03
-#define SEQ_ID_MEMORY_MODE	0x04
-#define SEQ_ID_UNKNOWN1		0x05
-#define SEQ_ID_UNKNOWN2		0x06
-#define SEQ_ID_UNKNOWN3		0x07
-/* S3 extensions */
-#define SEQ_ID_UNLOCK_EXT	0x08
-#define SEQ_ID_EXT_SEQ_REG9	0x09	/* b7 = 1 extended reg access by MMIO only */
-#define SEQ_ID_BUS_REQ_CNTL	0x0A
-#define SEQ_ID_EXT_MISC_SEQ	0x0B
-#define SEQ_ID_UNKNOWN4		0x0C
-#define SEQ_ID_EXT_SEQ		0x0D
-#define SEQ_ID_UNKNOWN5		0x0E
-#define SEQ_ID_UNKNOWN6		0x0F
-#define SEQ_ID_MCLK_LO		0x10
-#define SEQ_ID_MCLK_HI		0x11
-#define SEQ_ID_DCLK_LO		0x12
-#define SEQ_ID_DCLK_HI		0x13
-#define SEQ_ID_CLKSYN_CNTL_1	0x14
-#define SEQ_ID_CLKSYN_CNTL_2	0x15
-#define SEQ_ID_CLKSYN_TEST_HI	0x16	/* reserved for S3 testing of the */
-#define SEQ_ID_CLKSYN_TEST_LO	0x17	/* internal clock synthesizer   */
-#define SEQ_ID_RAMDAC_CNTL	0x18
-#define SEQ_ID_MORE_MAGIC	0x1A
-#define SEQ_ID_SIGNAL_SELECT	0x1C	/* new for virge */
-
-/* CRT Controller: */
-#define CRT_ADDRESS		0x03D4
-#define CRT_ADDRESS_R		0x03D5
-#define CRT_ADDRESS_W		0x03D5
-#define CRT_ID_HOR_TOTAL	0x00
-#define CRT_ID_HOR_DISP_ENA_END	0x01
-#define CRT_ID_START_HOR_BLANK	0x02
-#define CRT_ID_END_HOR_BLANK	0x03
-#define CRT_ID_START_HOR_RETR	0x04
-#define CRT_ID_END_HOR_RETR	0x05
-#define CRT_ID_VER_TOTAL	0x06
-#define CRT_ID_OVERFLOW		0x07
-#define CRT_ID_PRESET_ROW_SCAN	0x08
-#define CRT_ID_MAX_SCAN_LINE	0x09
-#define CRT_ID_CURSOR_START	0x0A
-#define CRT_ID_CURSOR_END	0x0B
-#define CRT_ID_START_ADDR_HIGH	0x0C
-#define CRT_ID_START_ADDR_LOW	0x0D
-#define CRT_ID_CURSOR_LOC_HIGH	0x0E
-#define CRT_ID_CURSOR_LOC_LOW	0x0F
-#define CRT_ID_START_VER_RETR	0x10
-#define CRT_ID_END_VER_RETR	0x11
-#define CRT_ID_VER_DISP_ENA_END	0x12
-#define CRT_ID_SCREEN_OFFSET	0x13
-#define CRT_ID_UNDERLINE_LOC	0x14
-#define CRT_ID_START_VER_BLANK	0x15
-#define CRT_ID_END_VER_BLANK	0x16
-#define CRT_ID_MODE_CONTROL	0x17
-#define CRT_ID_LINE_COMPARE	0x18
-#define CRT_ID_GD_LATCH_RBACK	0x22
-#define CRT_ID_ACT_TOGGLE_RBACK	0x24
-#define CRT_ID_ACT_INDEX_RBACK	0x26
-/* S3 extensions: S3 VGA Registers */
-#define CRT_ID_DEVICE_HIGH	0x2D
-#define CRT_ID_DEVICE_LOW	0x2E
-#define CRT_ID_REVISION 	0x2F
-#define CRT_ID_CHIP_ID_REV	0x30
-#define CRT_ID_MEMORY_CONF	0x31
-#define CRT_ID_BACKWAD_COMP_1	0x32
-#define CRT_ID_BACKWAD_COMP_2	0x33
-#define CRT_ID_BACKWAD_COMP_3	0x34
-#define CRT_ID_REGISTER_LOCK	0x35
-#define CRT_ID_CONFIG_1 	0x36
-#define CRT_ID_CONFIG_2 	0x37
-#define CRT_ID_REGISTER_LOCK_1	0x38
-#define CRT_ID_REGISTER_LOCK_2	0x39
-#define CRT_ID_MISC_1		0x3A
-#define CRT_ID_DISPLAY_FIFO	0x3B
-#define CRT_ID_LACE_RETR_START	0x3C
-/* S3 extensions: System Control Registers  */
-#define CRT_ID_SYSTEM_CONFIG	0x40
-#define CRT_ID_BIOS_FLAG	0x41
-#define CRT_ID_LACE_CONTROL	0x42
-#define CRT_ID_EXT_MODE 	0x43
-#define CRT_ID_HWGC_MODE	0x45	/* HWGC = Hardware Graphics Cursor */
-#define CRT_ID_HWGC_ORIGIN_X_HI	0x46
-#define CRT_ID_HWGC_ORIGIN_X_LO	0x47
-#define CRT_ID_HWGC_ORIGIN_Y_HI	0x48
-#define CRT_ID_HWGC_ORIGIN_Y_LO	0x49
-#define CRT_ID_HWGC_FG_STACK	0x4A
-#define CRT_ID_HWGC_BG_STACK	0x4B
-#define CRT_ID_HWGC_START_AD_HI	0x4C
-#define CRT_ID_HWGC_START_AD_LO	0x4D
-#define CRT_ID_HWGC_DSTART_X	0x4E
-#define CRT_ID_HWGC_DSTART_Y	0x4F
-/* S3 extensions: System Extension Registers  */
-#define CRT_ID_EXT_SYS_CNTL_1	0x50	/* NOT a virge register */
-#define CRT_ID_EXT_SYS_CNTL_2	0x51
-#define CRT_ID_EXT_BIOS_FLAG_1	0x52
-#define CRT_ID_EXT_MEM_CNTL_1	0x53
-#define CRT_ID_EXT_MEM_CNTL_2	0x54
-#define CRT_ID_EXT_DAC_CNTL	0x55
-#define CRT_ID_EX_SYNC_1	0x56
-#define CRT_ID_EX_SYNC_2	0x57
-#define CRT_ID_LAW_CNTL		0x58	/* LAW = Linear Address Window */
-#define CRT_ID_LAW_POS_HI	0x59
-#define CRT_ID_LAW_POS_LO	0x5A
-#define CRT_ID_GOUT_PORT	0x5C
-#define CRT_ID_EXT_HOR_OVF	0x5D
-#define CRT_ID_EXT_VER_OVF	0x5E
-#define CRT_ID_EXT_MEM_CNTL_3	0x60	/* NOT a virge register */
-#define CRT_ID_EXT_MEM_CNTL_4	0x61
-#define CRT_ID_EX_SYNC_3	0x63	/* NOT a virge register */
-#define CRT_ID_EXT_MISC_CNTL	0x65
-#define CRT_ID_EXT_MISC_CNTL_1	0x66
-#define CRT_ID_EXT_MISC_CNTL_2	0x67
-#define CRT_ID_CONFIG_3 	0x68
-#define CRT_ID_EXT_SYS_CNTL_3	0x69
-#define CRT_ID_EXT_SYS_CNTL_4	0x6A
-#define CRT_ID_EXT_BIOS_FLAG_3	0x6B
-#define CRT_ID_EXT_BIOS_FLAG_4	0x6C
-/* S3 virge extensions: more System Extension Registers  */
-#define CRT_ID_EXT_BIOS_FLAG_5	0x6D
-#define CRT_ID_EXT_DAC_TEST	0x6E
-#define CRT_ID_CONFIG_4 	0x6F
-
-/* Video DAC */
-#define VDAC_ADDRESS		0x03c8
-#define VDAC_ADDRESS_W		0x03c8
-#define VDAC_ADDRESS_R		0x03c7
-#define VDAC_STATE		0x03c7
-#define VDAC_DATA		0x03c9
-#define VDAC_MASK		0x03c6
-
-/* Miscellaneous Registers */
-#define MR_SUBSYSTEM_STATUS_R		0x8504	/* new for virge */
-#define MR_SUBSYSTEM_CNTL_W		0x8504	/* new for virge */
-#define MR_ADVANCED_FUNCTION_CONTROL	0x850C	/* new for virge */
-
-/* Blitter  */
-#define BLT_COMMAND_SET		0xA500
-#define BLT_SIZE_X_Y		0xA504
-#define BLT_SRC_X_Y		0xA508
-#define BLT_DEST_X_Y		0xA50C
-
-#define BLT_SRC_BASE		0xa4d4
-#define BLT_DEST_BASE		0xa4d8
-#define BLT_CLIP_LEFT_RIGHT	0xa4dc
-#define BLT_CLIP_TOP_BOTTOM	0xa4e0
-#define BLT_SRC_DEST_STRIDE	0xa4e4
-#define BLT_MONO_PATTERN_0	0xa4e8
-#define BLT_MONO_PATTERN_1	0xa4ec
-#define BLT_PATTERN_COLOR	0xa4f4
-
-#define L2D_COMMAND_SET		0xA900
-#define L2D_CLIP_LEFT_RIGHT	0xA8DC
-#define L2D_CLIP_TOP_BOTTOM	0xA8E0
-
-#define P2D_COMMAND_SET		0xAD00
-#define P2D_CLIP_LEFT_RIGHT	0xACDC
-#define P2D_CLIP_TOP_BOTTOM	0xACE0
-
-#define CMD_NOP		(0xf << 27)	/* %1111 << 27, was 0x07 */ 
-#define S3V_BITBLT	(0x0 << 27)
-#define S3V_RECTFILL	(0x2 << 27)
-#define S3V_AUTOEXE	0x01
-#define S3V_HWCLIP	0x02
-#define S3V_DRAW	0x20
-#define S3V_DST_8BPP	0x00
-#define S3V_DST_16BPP	0x04
-#define S3V_DST_24BPP	0x08
-#define S3V_MONO_PAT	0x100
-
-#define S3V_BLT_COPY	(0xcc<<17)
-#define S3V_BLT_CLEAR	(0x00<<17)
-#define S3V_BLT_SET	(0xff<<17)
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index b022fff..732db47 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -141,7 +141,7 @@
 {
 	int i;
 
-	for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+	for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i)
 		if (w1_therm_families[i].f->fid == fid)
 			return w1_therm_families[i].convert(rom);
 
@@ -238,7 +238,7 @@
 {
 	int err, i;
 
-	for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) {
+	for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i) {
 		err = w1_register_family(w1_therm_families[i].f);
 		if (err)
 			w1_therm_families[i].broken = 1;
@@ -251,7 +251,7 @@
 {
 	int i;
 
-	for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+	for (i = 0; i < ARRAY_SIZE(w1_therm_families); ++i)
 		if (!w1_therm_families[i].broken)
 			w1_unregister_family(w1_therm_families[i].f);
 }
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
index 60b05bc..b3ce885 100644
--- a/drivers/zorro/proc.c
+++ b/drivers/zorro/proc.c
@@ -75,7 +75,7 @@
 	return nbytes;
 }
 
-static struct file_operations proc_bus_zorro_operations = {
+static const struct file_operations proc_bus_zorro_operations = {
 	.llseek		= proc_bus_zorro_lseek,
 	.read		= proc_bus_zorro_read,
 };
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 378767c..5cf2213 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -41,10 +41,10 @@
 #include "v9fs_vfs.h"
 #include "fid.h"
 
-static struct inode_operations v9fs_dir_inode_operations;
-static struct inode_operations v9fs_dir_inode_operations_ext;
-static struct inode_operations v9fs_file_inode_operations;
-static struct inode_operations v9fs_symlink_inode_operations;
+static const struct inode_operations v9fs_dir_inode_operations;
+static const struct inode_operations v9fs_dir_inode_operations_ext;
+static const struct inode_operations v9fs_file_inode_operations;
+static const struct inode_operations v9fs_symlink_inode_operations;
 
 /**
  * unixmode2p9mode - convert unix mode bits to plan 9
@@ -1303,7 +1303,7 @@
 	return retval;
 }
 
-static struct inode_operations v9fs_dir_inode_operations_ext = {
+static const struct inode_operations v9fs_dir_inode_operations_ext = {
 	.create = v9fs_vfs_create,
 	.lookup = v9fs_vfs_lookup,
 	.symlink = v9fs_vfs_symlink,
@@ -1318,7 +1318,7 @@
 	.setattr = v9fs_vfs_setattr,
 };
 
-static struct inode_operations v9fs_dir_inode_operations = {
+static const struct inode_operations v9fs_dir_inode_operations = {
 	.create = v9fs_vfs_create,
 	.lookup = v9fs_vfs_lookup,
 	.unlink = v9fs_vfs_unlink,
@@ -1330,12 +1330,12 @@
 	.setattr = v9fs_vfs_setattr,
 };
 
-static struct inode_operations v9fs_file_inode_operations = {
+static const struct inode_operations v9fs_file_inode_operations = {
 	.getattr = v9fs_vfs_getattr,
 	.setattr = v9fs_vfs_setattr,
 };
 
-static struct inode_operations v9fs_symlink_inode_operations = {
+static const struct inode_operations v9fs_symlink_inode_operations = {
 	.readlink = v9fs_vfs_readlink,
 	.follow_link = v9fs_vfs_follow_link,
 	.put_link = v9fs_vfs_put_link,
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 63320d4..0ec42f6 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -45,7 +45,7 @@
 #include "fid.h"
 
 static void v9fs_clear_inode(struct inode *);
-static struct super_operations v9fs_super_ops;
+static const struct super_operations v9fs_super_ops;
 
 /**
  * v9fs_clear_inode - release an inode
@@ -263,7 +263,7 @@
 		v9fs_session_cancel(v9ses);
 }
 
-static struct super_operations v9fs_super_ops = {
+static const struct super_operations v9fs_super_ops = {
 	.statfs = simple_statfs,
 	.clear_inode = v9fs_clear_inode,
 	.show_options = v9fs_show_options,
diff --git a/fs/Kconfig b/fs/Kconfig
index 11c5932..488521e 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1088,7 +1088,7 @@
 
 config ECRYPT_FS
 	tristate "eCrypt filesystem layer support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && KEYS && CRYPTO
+	depends on EXPERIMENTAL && KEYS && CRYPTO && NET
 	help
 	  Encrypted filesystem that operates on the VFS layer.  See
 	  <file:Documentation/ecryptfs.txt> to learn more about
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index 29217ff..936f2af 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -84,7 +84,7 @@
  */
 
 /* dir_*.c */
-extern struct inode_operations adfs_dir_inode_operations;
+extern const struct inode_operations adfs_dir_inode_operations;
 extern const struct file_operations adfs_dir_operations;
 extern struct dentry_operations adfs_dentry_operations;
 extern struct adfs_dir_ops adfs_f_dir_ops;
@@ -93,7 +93,7 @@
 extern int adfs_dir_update(struct super_block *sb, struct object_info *obj);
 
 /* file.c */
-extern struct inode_operations adfs_file_inode_operations;
+extern const struct inode_operations adfs_file_inode_operations;
 extern const struct file_operations adfs_file_operations;
 
 static inline __u32 signed_asl(__u32 val, signed int shift)
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index 2b89038..fc1a8dc 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -295,7 +295,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations adfs_dir_inode_operations = {
+const struct inode_operations adfs_dir_inode_operations = {
 	.lookup		= adfs_lookup,
 	.setattr	= adfs_notify_change,
 };
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index 6101ea6..f544a28 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -36,6 +36,6 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations adfs_file_inode_operations = {
+const struct inode_operations adfs_file_inode_operations = {
 	.setattr	= adfs_notify_change,
 };
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 5023351..2e5f2c8 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -254,7 +254,7 @@
 	kmem_cache_destroy(adfs_inode_cachep);
 }
 
-static struct super_operations adfs_sops = {
+static const struct super_operations adfs_sops = {
 	.alloc_inode	= adfs_alloc_inode,
 	.destroy_inode	= adfs_destroy_inode,
 	.write_inode	= adfs_write_inode,
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index 1dc8438..7db2d28 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -188,9 +188,9 @@
 
 /* jump tables */
 
-extern struct inode_operations	 affs_file_inode_operations;
-extern struct inode_operations	 affs_dir_inode_operations;
-extern struct inode_operations   affs_symlink_inode_operations;
+extern const struct inode_operations	 affs_file_inode_operations;
+extern const struct inode_operations	 affs_dir_inode_operations;
+extern const struct inode_operations   affs_symlink_inode_operations;
 extern const struct file_operations	 affs_file_operations;
 extern const struct file_operations	 affs_file_operations_ofs;
 extern const struct file_operations	 affs_dir_operations;
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index cad3ee3..6e3f282 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -26,7 +26,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations affs_dir_inode_operations = {
+const struct inode_operations affs_dir_inode_operations = {
 	.create		= affs_create,
 	.lookup		= affs_lookup,
 	.link		= affs_link,
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 05b5e22..4aa8079 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -38,7 +38,7 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations affs_file_inode_operations = {
+const struct inode_operations affs_file_inode_operations = {
 	.truncate	= affs_truncate,
 	.setattr	= affs_notify_change,
 };
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 44d439c..fce6848 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -12,7 +12,7 @@
 
 #include "affs.h"
 
-extern struct inode_operations affs_symlink_inode_operations;
+extern const struct inode_operations affs_symlink_inode_operations;
 extern struct timezone sys_tz;
 
 void
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 3de93e7..a324045 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -112,7 +112,7 @@
 	kmem_cache_destroy(affs_inode_cachep);
 }
 
-static struct super_operations affs_sops = {
+static const struct super_operations affs_sops = {
 	.alloc_inode	= affs_alloc_inode,
 	.destroy_inode	= affs_destroy_inode,
 	.read_inode	= affs_read_inode,
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c
index f802256..4178253 100644
--- a/fs/affs/symlink.c
+++ b/fs/affs/symlink.c
@@ -70,7 +70,7 @@
 	.readpage	= affs_symlink_readpage,
 };
 
-struct inode_operations affs_symlink_inode_operations = {
+const struct inode_operations affs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 4acd041..9908462 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -37,7 +37,7 @@
 	.readdir	= afs_dir_readdir,
 };
 
-struct inode_operations afs_dir_inode_operations = {
+const struct inode_operations afs_dir_inode_operations = {
 	.lookup		= afs_dir_lookup,
 	.getattr	= afs_inode_getattr,
 #if 0 /* TODO */
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 2e8c426..eeff14c 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -30,7 +30,7 @@
 static void afs_file_invalidatepage(struct page *page, unsigned long offset);
 static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
 
-struct inode_operations afs_file_inode_operations = {
+const struct inode_operations afs_file_inode_operations = {
 	.getattr	= afs_inode_getattr,
 };
 
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index e88b3b6..5151d5d 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -63,14 +63,14 @@
 /*
  * dir.c
  */
-extern struct inode_operations afs_dir_inode_operations;
+extern const struct inode_operations afs_dir_inode_operations;
 extern const struct file_operations afs_dir_file_operations;
 
 /*
  * file.c
  */
 extern const struct address_space_operations afs_fs_aops;
-extern struct inode_operations afs_file_inode_operations;
+extern const struct inode_operations afs_file_inode_operations;
 
 #ifdef AFS_CACHING_SUPPORT
 extern int afs_cache_get_page_cookie(struct page *page,
@@ -104,7 +104,7 @@
 /*
  * mntpt.c
  */
-extern struct inode_operations afs_mntpt_inode_operations;
+extern const struct inode_operations afs_mntpt_inode_operations;
 extern const struct file_operations afs_mntpt_file_operations;
 extern struct afs_timer afs_mntpt_expiry_timer;
 extern struct afs_timer_ops afs_mntpt_expiry_timer_ops;
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 8f74e84..fdf23b2 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -36,7 +36,7 @@
 	.open		= afs_mntpt_open,
 };
 
-struct inode_operations afs_mntpt_inode_operations = {
+const struct inode_operations afs_mntpt_inode_operations = {
 	.lookup		= afs_mntpt_lookup,
 	.follow_link	= afs_mntpt_follow_link,
 	.readlink	= page_readlink,
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 18d9b77..eb7e323 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -56,7 +56,7 @@
 	.fs_flags	= FS_BINARY_MOUNTDATA,
 };
 
-static struct super_operations afs_super_ops = {
+static const struct super_operations afs_super_ops = {
 	.statfs		= simple_statfs,
 	.alloc_inode	= afs_alloc_inode,
 	.drop_inode	= generic_delete_inode,
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 906ba5c..4ef5444 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -142,8 +142,8 @@
 
 /* Operations structures */
 
-extern struct inode_operations autofs_root_inode_operations;
-extern struct inode_operations autofs_symlink_inode_operations;
+extern const struct inode_operations autofs_root_inode_operations;
+extern const struct inode_operations autofs_symlink_inode_operations;
 extern const struct file_operations autofs_root_operations;
 
 /* Initializing function */
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index f968d13..aa0b61f 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -52,7 +52,7 @@
 
 static void autofs_read_inode(struct inode *inode);
 
-static struct super_operations autofs_sops = {
+static const struct super_operations autofs_sops = {
 	.read_inode	= autofs_read_inode,
 	.statfs		= simple_statfs,
 };
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index e698c51..f259720 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -32,7 +32,7 @@
 	.ioctl		= autofs_root_ioctl,
 };
 
-struct inode_operations autofs_root_inode_operations = {
+const struct inode_operations autofs_root_inode_operations = {
         .lookup		= autofs_root_lookup,
         .unlink		= autofs_root_unlink,
         .symlink	= autofs_root_symlink,
diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c
index c74f2eb..7ce9cb2 100644
--- a/fs/autofs/symlink.c
+++ b/fs/autofs/symlink.c
@@ -20,7 +20,7 @@
 	return NULL;
 }
 
-struct inode_operations autofs_symlink_inode_operations = {
+const struct inode_operations autofs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= autofs_follow_link
 };
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 216b1a3..6b4cec3 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -168,11 +168,11 @@
 
 /* Operations structures */
 
-extern struct inode_operations autofs4_symlink_inode_operations;
-extern struct inode_operations autofs4_dir_inode_operations;
-extern struct inode_operations autofs4_root_inode_operations;
-extern struct inode_operations autofs4_indirect_root_inode_operations;
-extern struct inode_operations autofs4_direct_root_inode_operations;
+extern const struct inode_operations autofs4_symlink_inode_operations;
+extern const struct inode_operations autofs4_dir_inode_operations;
+extern const struct inode_operations autofs4_root_inode_operations;
+extern const struct inode_operations autofs4_indirect_root_inode_operations;
+extern const struct inode_operations autofs4_direct_root_inode_operations;
 extern const struct file_operations autofs4_dir_operations;
 extern const struct file_operations autofs4_root_operations;
 
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index e8f6c5a..5e458e0 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -196,7 +196,7 @@
 	return 0;
 }
 
-static struct super_operations autofs4_sops = {
+static const struct super_operations autofs4_sops = {
 	.statfs		= simple_statfs,
 	.show_options	= autofs4_show_options,
 };
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 8d05b9f..47fee96 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -47,7 +47,7 @@
 	.readdir	= autofs4_dir_readdir,
 };
 
-struct inode_operations autofs4_indirect_root_inode_operations = {
+const struct inode_operations autofs4_indirect_root_inode_operations = {
 	.lookup		= autofs4_lookup,
 	.unlink		= autofs4_dir_unlink,
 	.symlink	= autofs4_dir_symlink,
@@ -55,7 +55,7 @@
 	.rmdir		= autofs4_dir_rmdir,
 };
 
-struct inode_operations autofs4_direct_root_inode_operations = {
+const struct inode_operations autofs4_direct_root_inode_operations = {
 	.lookup		= autofs4_lookup,
 	.unlink		= autofs4_dir_unlink,
 	.mkdir		= autofs4_dir_mkdir,
@@ -63,7 +63,7 @@
 	.follow_link	= autofs4_follow_link,
 };
 
-struct inode_operations autofs4_dir_inode_operations = {
+const struct inode_operations autofs4_dir_inode_operations = {
 	.lookup		= autofs4_lookup,
 	.unlink		= autofs4_dir_unlink,
 	.symlink	= autofs4_dir_symlink,
diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c
index 2ea2c98..b4ea829 100644
--- a/fs/autofs4/symlink.c
+++ b/fs/autofs4/symlink.c
@@ -19,7 +19,7 @@
 	return NULL;
 }
 
-struct inode_operations autofs4_symlink_inode_operations = {
+const struct inode_operations autofs4_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= autofs4_follow_link
 };
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 869f519..efeab2f 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -291,7 +291,7 @@
 	return -EIO;
 }
 
-static struct inode_operations bad_inode_ops =
+static const struct inode_operations bad_inode_ops =
 {
 	.create		= bad_inode_create,
 	.lookup		= bad_inode_lookup,
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 481e59b..cc6cc8e 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -68,7 +68,7 @@
 	.readdir	= befs_readdir,
 };
 
-static struct inode_operations befs_dir_inode_operations = {
+static const struct inode_operations befs_dir_inode_operations = {
 	.lookup		= befs_lookup,
 };
 
@@ -78,7 +78,7 @@
 	.bmap		= befs_bmap,
 };
 
-static struct inode_operations befs_symlink_inode_operations = {
+static const struct inode_operations befs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= befs_follow_link,
 	.put_link	= befs_put_link,
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 31973bb..130f6c6 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -48,12 +48,12 @@
 
 
 /* file.c */
-extern struct inode_operations bfs_file_inops;
+extern const struct inode_operations bfs_file_inops;
 extern const struct file_operations bfs_file_operations;
 extern const struct address_space_operations bfs_aops;
 
 /* dir.c */
-extern struct inode_operations bfs_dir_inops;
+extern const struct inode_operations bfs_dir_inops;
 extern const struct file_operations bfs_dir_operations;
 
 #endif /* _FS_BFS_BFS_H */
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 2a746e6..097f149 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -260,7 +260,7 @@
 	return error;
 }
 
-struct inode_operations bfs_dir_inops = {
+const struct inode_operations bfs_dir_inops = {
 	.create			= bfs_create,
 	.lookup			= bfs_lookup,
 	.link			= bfs_link,
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index a9164a8..ef4d1fa 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -164,4 +164,4 @@
 	.bmap		= bfs_bmap,
 };
 
-struct inode_operations bfs_file_inops;
+const struct inode_operations bfs_file_inops;
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 134c999..93d6219 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -270,7 +270,7 @@
 	kmem_cache_destroy(bfs_inode_cachep);
 }
 
-static struct super_operations bfs_sops = {
+static const struct super_operations bfs_sops = {
 	.alloc_inode	= bfs_alloc_inode,
 	.destroy_inode	= bfs_destroy_inode,
 	.read_inode	= bfs_read_inode,
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index c2e0825..e6f5799 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -719,7 +719,7 @@
 
 /* Superblock handling */
 
-static struct super_operations s_ops = {
+static const struct super_operations s_ops = {
 	.statfs		= simple_statfs,
 	.clear_inode	= bm_clear_inode,
 };
diff --git a/fs/block_dev.c b/fs/block_dev.c
index fc7028b6..0c59b70 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -489,7 +489,7 @@
 	spin_unlock(&bdev_lock);
 }
 
-static struct super_operations bdev_sops = {
+static const struct super_operations bdev_sops = {
 	.statfs = simple_statfs,
 	.alloc_inode = bdev_alloc_inode,
 	.destroy_inode = bdev_destroy_inode,
diff --git a/fs/buffer.c b/fs/buffer.c
index 7ff6e93..f99c509 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1283,11 +1283,11 @@
  * Look up the bh in this cpu's LRU.  If it's there, move it to the head.
  */
 static struct buffer_head *
-lookup_bh_lru(struct block_device *bdev, sector_t block, int size)
+lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *ret = NULL;
 	struct bh_lru *lru;
-	int i;
+	unsigned int i;
 
 	check_irqs_on();
 	bh_lru_lock();
@@ -1319,7 +1319,7 @@
  * NULL
  */
 struct buffer_head *
-__find_get_block(struct block_device *bdev, sector_t block, int size)
+__find_get_block(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *bh = lookup_bh_lru(bdev, block, size);
 
@@ -1347,7 +1347,7 @@
  * attempt is failing.  FIXME, perhaps?
  */
 struct buffer_head *
-__getblk(struct block_device *bdev, sector_t block, int size)
+__getblk(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *bh = __find_get_block(bdev, block, size);
 
@@ -1361,7 +1361,7 @@
 /*
  * Do async read-ahead on a buffer..
  */
-void __breadahead(struct block_device *bdev, sector_t block, int size)
+void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *bh = __getblk(bdev, block, size);
 	if (likely(bh)) {
@@ -1381,7 +1381,7 @@
  *  It returns NULL if the block was unreadable.
  */
 struct buffer_head *
-__bread(struct block_device *bdev, sector_t block, int size)
+__bread(struct block_device *bdev, sector_t block, unsigned size)
 {
 	struct buffer_head *bh = __getblk(bdev, block, size);
 
@@ -1440,6 +1440,7 @@
 	clear_buffer_req(bh);
 	clear_buffer_new(bh);
 	clear_buffer_delay(bh);
+	clear_buffer_unwritten(bh);
 	unlock_buffer(bh);
 }
 
@@ -1823,6 +1824,7 @@
 			continue; 
 		}
 		if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
+		    !buffer_unwritten(bh) &&
 		     (block_start < from || block_end > to)) {
 			ll_rw_block(READ, 1, &bh);
 			*wait_bh++=bh;
@@ -2544,7 +2546,7 @@
 	if (PageUptodate(page))
 		set_buffer_uptodate(bh);
 
-	if (!buffer_uptodate(bh) && !buffer_delay(bh)) {
+	if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) {
 		err = -EIO;
 		ll_rw_block(READ, 1, &bh);
 		wait_on_buffer(bh);
diff --git a/fs/char_dev.c b/fs/char_dev.c
index a885f46..e6194e2 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -108,6 +108,13 @@
 	/* temporary */
 	if (major == 0) {
 		for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {
+			/*
+			 * Disallow the LANANA-assigned LOCAL/EXPERIMENTAL
+			 * majors
+			 */
+			if ((60 <= i && i <= 63) || (120 <= i && i <= 127) ||
+					(240 <= i && i <= 254))
+				continue;
 			if (chrdevs[i] == NULL)
 				break;
 		}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 93ef099..e8287c4 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -64,7 +64,7 @@
 struct task_struct * oplockThread = NULL;
 extern struct task_struct * dnotifyThread; /* remove sparse warning */
 struct task_struct * dnotifyThread = NULL;
-static struct super_operations cifs_super_ops; 
+static const struct super_operations cifs_super_ops;
 unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
 module_param(CIFSMaxBufSize, int, 0);
 MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
@@ -453,7 +453,7 @@
 	return 0;
 }
 
-static struct super_operations cifs_super_ops = {
+static const struct super_operations cifs_super_ops = {
 	.read_inode = cifs_read_inode,
 	.put_super = cifs_put_super,
 	.statfs = cifs_statfs,
@@ -533,7 +533,7 @@
 	.kill_sb = kill_anon_super,
 	/*  .fs_flags */
 };
-struct inode_operations cifs_dir_inode_ops = {
+const struct inode_operations cifs_dir_inode_ops = {
 	.create = cifs_create,
 	.lookup = cifs_lookup,
 	.getattr = cifs_getattr,
@@ -555,7 +555,7 @@
 #endif
 };
 
-struct inode_operations cifs_file_inode_ops = {
+const struct inode_operations cifs_file_inode_ops = {
 /*	revalidate:cifs_revalidate, */
 	.setattr = cifs_setattr,
 	.getattr = cifs_getattr, /* do we need this anymore? */
@@ -569,7 +569,7 @@
 #endif 
 };
 
-struct inode_operations cifs_symlink_inode_ops = {
+const struct inode_operations cifs_symlink_inode_ops = {
 	.readlink = generic_readlink, 
 	.follow_link = cifs_follow_link,
 	.put_link = cifs_put_link,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 8aa66dc..01ae24a 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -36,13 +36,13 @@
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
 /* Functions related to super block operations */
-/* extern struct super_operations cifs_super_ops;*/
+/* extern const struct super_operations cifs_super_ops;*/
 extern void cifs_read_inode(struct inode *);
 extern void cifs_delete_inode(struct inode *);
 /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
 
 /* Functions related to inodes */
-extern struct inode_operations cifs_dir_inode_ops;
+extern const struct inode_operations cifs_dir_inode_ops;
 extern int cifs_create(struct inode *, struct dentry *, int, 
 		       struct nameidata *);
 extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
@@ -58,8 +58,8 @@
 extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int cifs_setattr(struct dentry *, struct iattr *);
 
-extern struct inode_operations cifs_file_inode_ops;
-extern struct inode_operations cifs_symlink_inode_ops;
+extern const struct inode_operations cifs_file_inode_ops;
+extern const struct inode_operations cifs_symlink_inode_ops;
 
 /* Functions related to files and directories */
 extern const struct file_operations cifs_file_ops;
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
index 4c9fecb..28c8727 100644
--- a/fs/coda/cnode.c
+++ b/fs/coda/cnode.c
@@ -16,7 +16,7 @@
 	return memcmp(fid1, fid2, sizeof(*fid1)) == 0;
 }
 
-static struct inode_operations coda_symlink_inode_operations = {
+static const struct inode_operations coda_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 0c6f7f3..9ddf5ed 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -66,7 +66,7 @@
 	.d_delete	= coda_dentry_delete,
 };
 
-struct inode_operations coda_dir_inode_operations =
+const struct inode_operations coda_dir_inode_operations =
 {
 	.create		= coda_create,
 	.lookup		= coda_lookup,
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 01395de..614175a 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -90,7 +90,7 @@
 }
 
 /* exported operations */
-static struct super_operations coda_super_operations =
+static const struct super_operations coda_super_operations =
 {
 	.alloc_inode	= coda_alloc_inode,
 	.destroy_inode	= coda_destroy_inode,
@@ -271,7 +271,7 @@
 	return error;
 }
 
-struct inode_operations coda_file_inode_operations = {
+const struct inode_operations coda_file_inode_operations = {
 	.permission	= coda_permission,
 	.getattr	= coda_getattr,
 	.setattr	= coda_setattr,
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 214822b..2bf3026 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -30,7 +30,7 @@
                        unsigned int cmd, unsigned long user_data);
 
 /* exported from this file */
-struct inode_operations coda_ioctl_inode_operations =
+const struct inode_operations coda_ioctl_inode_operations =
 {
 	.permission	= coda_ioctl_permission,
 	.setattr	= coda_setattr,
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index f92cd30..7b48c03 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -75,8 +75,8 @@
 extern const struct file_operations configfs_dir_operations;
 extern const struct file_operations configfs_file_operations;
 extern const struct file_operations bin_fops;
-extern struct inode_operations configfs_dir_inode_operations;
-extern struct inode_operations configfs_symlink_inode_operations;
+extern const struct inode_operations configfs_dir_inode_operations;
+extern const struct inode_operations configfs_symlink_inode_operations;
 
 extern int configfs_symlink(struct inode *dir, struct dentry *dentry,
 			    const char *symname);
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 9371ee2..34750d5 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -930,7 +930,7 @@
 	return 0;
 }
 
-struct inode_operations configfs_dir_inode_operations = {
+const struct inode_operations configfs_dir_inode_operations = {
 	.mkdir		= configfs_mkdir,
 	.rmdir		= configfs_rmdir,
 	.symlink	= configfs_symlink,
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index fb18917..2ec9bea 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -49,7 +49,7 @@
 	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
 };
 
-static struct inode_operations configfs_inode_operations ={
+static const struct inode_operations configfs_inode_operations ={
 	.setattr	= configfs_setattr,
 };
 
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index ed67852..6f57300 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -41,7 +41,7 @@
 struct kmem_cache *configfs_dir_cachep;
 static int configfs_mnt_count = 0;
 
-static struct super_operations configfs_ops = {
+static const struct super_operations configfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
 };
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
index fb65e08..22700d2 100644
--- a/fs/configfs/symlink.c
+++ b/fs/configfs/symlink.c
@@ -272,7 +272,7 @@
 	}
 }
 
-struct inode_operations configfs_symlink_inode_operations = {
+const struct inode_operations configfs_symlink_inode_operations = {
 	.follow_link = configfs_follow_link,
 	.readlink = generic_readlink,
 	.put_link = configfs_put_link,
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 6db03fb..facd0c8 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -27,8 +27,8 @@
 
 #include <asm/uaccess.h>
 
-static struct super_operations cramfs_ops;
-static struct inode_operations cramfs_dir_inode_operations;
+static const struct super_operations cramfs_ops;
+static const struct inode_operations cramfs_dir_inode_operations;
 static const struct file_operations cramfs_directory_operations;
 static const struct address_space_operations cramfs_aops;
 
@@ -518,11 +518,11 @@
 	.readdir	= cramfs_readdir,
 };
 
-static struct inode_operations cramfs_dir_inode_operations = {
+static const struct inode_operations cramfs_dir_inode_operations = {
 	.lookup		= cramfs_lookup,
 };
 
-static struct super_operations cramfs_ops = {
+static const struct super_operations cramfs_ops = {
 	.put_super	= cramfs_put_super,
 	.remount_fs	= cramfs_remount,
 	.statfs		= cramfs_statfs,
diff --git a/fs/dcache.c b/fs/dcache.c
index d68631f..b5f6139 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1739,45 +1739,41 @@
  * @rootmnt: vfsmnt to which the root dentry belongs
  * @buffer: buffer to return value in
  * @buflen: buffer length
+ * @fail_deleted: what to return for deleted files
  *
- * Convert a dentry into an ASCII path name. If the entry has been deleted
- * the string " (deleted)" is appended. Note that this is ambiguous.
+ * Convert a dentry into an ASCII path name. If the entry has been deleted,
+ * then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
+ * the the string " (deleted)" is appended. Note that this is ambiguous.
  *
- * Returns the buffer or an error code if the path was too long.
- *
- * "buflen" should be positive. Caller holds the dcache_lock.
+ * Returns the buffer or an error code.
  */
-static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
-			struct dentry *root, struct vfsmount *rootmnt,
-			char *buffer, int buflen)
+static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+		      struct dentry *root, struct vfsmount *rootmnt,
+		      char *buffer, int buflen, int fail_deleted)
 {
-	char * end = buffer+buflen;
-	char * retval;
-	int namelen;
+	int namelen, is_slash;
 
-	*--end = '\0';
-	buflen--;
+	if (buflen < 2)
+		return ERR_PTR(-ENAMETOOLONG);
+	buffer += --buflen;
+	*buffer = '\0';
+
+	spin_lock(&dcache_lock);
 	if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
-		buflen -= 10;
-		end -= 10;
-		if (buflen < 0)
+		if (fail_deleted) {
+			buffer = ERR_PTR(-ENOENT);
+			goto out;
+		}
+		if (buflen < 10)
 			goto Elong;
-		memcpy(end, " (deleted)", 10);
+		buflen -= 10;
+		buffer -= 10;
+		memcpy(buffer, " (deleted)", 10);
 	}
-
-	if (buflen < 1)
-		goto Elong;
-	/* Get '/' right */
-	retval = end-1;
-	*retval = '/';
-
-	for (;;) {
+	while (dentry != root || vfsmnt != rootmnt) {
 		struct dentry * parent;
 
-		if (dentry == root && vfsmnt == rootmnt)
-			break;
 		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
-			/* Global root? */
 			spin_lock(&vfsmount_lock);
 			if (vfsmnt->mnt_parent == vfsmnt) {
 				spin_unlock(&vfsmount_lock);
@@ -1791,33 +1787,60 @@
 		parent = dentry->d_parent;
 		prefetch(parent);
 		namelen = dentry->d_name.len;
-		buflen -= namelen + 1;
-		if (buflen < 0)
+		if (buflen <= namelen)
 			goto Elong;
-		end -= namelen;
-		memcpy(end, dentry->d_name.name, namelen);
-		*--end = '/';
-		retval = end;
+		buflen -= namelen + 1;
+		buffer -= namelen;
+		memcpy(buffer, dentry->d_name.name, namelen);
+		*--buffer = '/';
 		dentry = parent;
 	}
+	/* Get '/' right */
+	if (*buffer != '/')
+		*--buffer = '/';
 
-	return retval;
+out:
+	spin_unlock(&dcache_lock);
+	return buffer;
 
 global_root:
+	/*
+	 * We went past the (vfsmount, dentry) we were looking for and have
+	 * either hit a root dentry, a lazily unmounted dentry, an
+	 * unconnected dentry, or the file is on a pseudo filesystem.
+	 */
 	namelen = dentry->d_name.len;
-	buflen -= namelen;
-	if (buflen < 0)
+	is_slash = (namelen == 1 && *dentry->d_name.name == '/');
+	if (is_slash || (dentry->d_sb->s_flags & MS_NOUSER)) {
+		/*
+		 * Make sure we won't return a pathname starting with '/'.
+		 *
+		 * Historically, we also glue together the root dentry and
+		 * remaining name for pseudo filesystems like pipefs, which
+		 * have the MS_NOUSER flag set. This results in pathnames
+		 * like "pipe:[439336]".
+		 */
+		if (*buffer == '/') {
+			buffer++;
+			buflen++;
+		}
+		if (is_slash)
+			goto out;
+	}
+	if (buflen < namelen)
 		goto Elong;
-	retval -= namelen-1;	/* hit the slash */
-	memcpy(retval, dentry->d_name.name, namelen);
-	return retval;
+	buffer -= namelen;
+	memcpy(buffer, dentry->d_name.name, namelen);
+	goto out;
+
 Elong:
-	return ERR_PTR(-ENAMETOOLONG);
+	buffer = ERR_PTR(-ENAMETOOLONG);
+	goto out;
 }
 
 /* write full pathname into buffer and return start of pathname */
-char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
-				char *buf, int buflen)
+char *d_path(struct dentry *dentry, struct vfsmount *vfsmnt, char *buf,
+	     int buflen)
 {
 	char *res;
 	struct vfsmount *rootmnt;
@@ -1827,9 +1850,7 @@
 	rootmnt = mntget(current->fs->rootmnt);
 	root = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
-	spin_lock(&dcache_lock);
-	res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
-	spin_unlock(&dcache_lock);
+	res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, 0);
 	dput(root);
 	mntput(rootmnt);
 	return res;
@@ -1855,10 +1876,10 @@
  */
 asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
 {
-	int error;
+	int error, len;
 	struct vfsmount *pwdmnt, *rootmnt;
 	struct dentry *pwd, *root;
-	char *page = (char *) __get_free_page(GFP_USER);
+	char *page = (char *) __get_free_page(GFP_USER), *cwd;
 
 	if (!page)
 		return -ENOMEM;
@@ -1870,29 +1891,18 @@
 	root = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
 
-	error = -ENOENT;
-	/* Has the current directory has been unlinked? */
-	spin_lock(&dcache_lock);
-	if (pwd->d_parent == pwd || !d_unhashed(pwd)) {
-		unsigned long len;
-		char * cwd;
+	cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 1);
+	error = PTR_ERR(cwd);
+	if (IS_ERR(cwd))
+		goto out;
 
-		cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
-		spin_unlock(&dcache_lock);
-
-		error = PTR_ERR(cwd);
-		if (IS_ERR(cwd))
-			goto out;
-
-		error = -ERANGE;
-		len = PAGE_SIZE + page - cwd;
-		if (len <= size) {
-			error = len;
-			if (copy_to_user(buf, cwd, len))
-				error = -EFAULT;
-		}
-	} else
-		spin_unlock(&dcache_lock);
+	error = -ERANGE;
+	len = PAGE_SIZE + page - cwd;
+	if (len <= size) {
+		error = len;
+		if (copy_to_user(buf, cwd, len))
+			error = -EFAULT;
+	}
 
 out:
 	dput(pwd);
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index bf3901a..8d130cc 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -254,7 +254,7 @@
 			blob->size);
 }
 
-static struct file_operations fops_blob = {
+static const struct file_operations fops_blob = {
 	.read =		read_file_blob,
 	.open =		default_open,
 };
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 5f7b5a6..643e57b 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -91,7 +91,7 @@
 	return 0;
 }
 
-static struct super_operations devpts_sops = {
+static const struct super_operations devpts_sops = {
 	.statfs		= simple_statfs,
 	.remount_fs	= devpts_remount,
 };
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index ca94a83..61ba670 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -287,7 +287,7 @@
 	return 0;
 }
 
-static struct file_operations rsb_fops = {
+static const struct file_operations rsb_fops = {
 	.owner   = THIS_MODULE,
 	.open    = rsb_open,
 	.read    = seq_read,
@@ -331,7 +331,7 @@
 	return rv;
 }
 
-static struct file_operations waiters_fops = {
+static const struct file_operations waiters_fops = {
 	.owner   = THIS_MODULE,
 	.open    = waiters_open,
 	.read    = waiters_read
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index d378b7f..40db61d 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -25,7 +25,7 @@
 
 static const char *name_prefix="dlm";
 static struct miscdevice ctl_device;
-static struct file_operations device_fops;
+static const struct file_operations device_fops;
 
 #ifdef CONFIG_COMPAT
 
@@ -759,7 +759,7 @@
 	return 0;
 }
 
-static struct file_operations device_fops = {
+static const struct file_operations device_fops = {
 	.open    = device_open,
 	.release = device_close,
 	.read    = device_read,
@@ -768,7 +768,7 @@
 	.owner   = THIS_MODULE,
 };
 
-static struct file_operations ctl_device_fops = {
+static const struct file_operations ctl_device_fops = {
 	.open    = ctl_device_open,
 	.release = ctl_device_close,
 	.write   = device_write,
diff --git a/fs/dquot.c b/fs/dquot.c
index a561fb2..9eb166f 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -79,6 +79,7 @@
 #include <linux/buffer_head.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <linux/writeback.h> /* for inode_lock, oddly enough.. */
 
 #include <asm/uaccess.h>
 
@@ -687,23 +688,27 @@
 /* This routine is guarded by dqonoff_mutex mutex */
 static void add_dquot_ref(struct super_block *sb, int type)
 {
-	struct list_head *p;
+	struct inode *inode;
 
 restart:
-	file_list_lock();
-	list_for_each(p, &sb->s_files) {
-		struct file *filp = list_entry(p, struct file, f_u.fu_list);
-		struct inode *inode = filp->f_path.dentry->d_inode;
-		if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
-			struct dentry *dentry = dget(filp->f_path.dentry);
-			file_list_unlock();
-			sb->dq_op->initialize(inode, type);
-			dput(dentry);
-			/* As we may have blocked we had better restart... */
-			goto restart;
-		}
+	spin_lock(&inode_lock);
+	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+		if (!atomic_read(&inode->i_writecount))
+			continue;
+		if (!dqinit_needed(inode, type))
+			continue;
+		if (inode->i_state & (I_FREEING|I_WILL_FREE))
+			continue;
+
+		__iget(inode);
+		spin_unlock(&inode_lock);
+
+		sb->dq_op->initialize(inode, type);
+		iput(inode);
+		/* As we may have blocked we had better restart... */
+		goto restart;
 	}
-	file_list_unlock();
+	spin_unlock(&inode_lock);
 }
 
 /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
@@ -755,15 +760,30 @@
 	}
 }
 
+static void remove_dquot_ref(struct super_block *sb, int type,
+		struct list_head *tofree_head)
+{
+	struct inode *inode;
+
+	spin_lock(&inode_lock);
+	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+		if (!IS_NOQUOTA(inode))
+			remove_inode_dquot_ref(inode, type, tofree_head);
+	}
+	spin_unlock(&inode_lock);
+}
+
 /* Gather all references from inodes and drop them */
 static void drop_dquot_ref(struct super_block *sb, int type)
 {
 	LIST_HEAD(tofree_head);
 
-	down_write(&sb_dqopt(sb)->dqptr_sem);
-	remove_dquot_ref(sb, type, &tofree_head);
-	up_write(&sb_dqopt(sb)->dqptr_sem);
-	put_dquot_list(&tofree_head);
+	if (sb->dq_op) {
+		down_write(&sb_dqopt(sb)->dqptr_sem);
+		remove_dquot_ref(sb, type, &tofree_head);
+		up_write(&sb_dqopt(sb)->dqptr_sem);
+		put_dquot_list(&tofree_head);
+	}
 }
 
 static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
diff --git a/fs/ecryptfs/Makefile b/fs/ecryptfs/Makefile
index ca65624..1f11072 100644
--- a/fs/ecryptfs/Makefile
+++ b/fs/ecryptfs/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
 
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o messaging.o netlink.o debug.o
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 75bbfae..6ac6306 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1997-2004 Erez Zadok
  * Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *   		Michael C. Thompson <mcthomps@us.ibm.com>
  *
@@ -207,7 +207,7 @@
 	mutex_init(&crypt_stat->cs_mutex);
 	mutex_init(&crypt_stat->cs_tfm_mutex);
 	mutex_init(&crypt_stat->cs_hash_tfm_mutex);
-	ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED);
+	crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED;
 }
 
 /**
@@ -305,8 +305,7 @@
 	int rc = 0;
 
 	BUG_ON(!crypt_stat || !crypt_stat->tfm
-	       || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-				       ECRYPTFS_STRUCT_INITIALIZED));
+	       || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
 	if (unlikely(ecryptfs_verbosity > 0)) {
 		ecryptfs_printk(KERN_DEBUG, "Key size [%d]; key:\n",
 				crypt_stat->key_size);
@@ -429,10 +428,10 @@
 			goto out;
 		}
 	} else {
-		rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL,
-						      lower_inode,
-						      lower_page_idx);
-		if (rc) {
+		*lower_page = grab_cache_page(lower_inode->i_mapping,
+					      lower_page_idx);
+		if (!(*lower_page)) {
+			rc = -EINVAL;
 			ecryptfs_printk(
 				KERN_ERR, "Error attempting to grab and map "
 				"lower page with index [0x%.16x]; rc = [%d]\n",
@@ -485,7 +484,7 @@
 	lower_inode = ecryptfs_inode_to_lower(ctx->page->mapping->host);
 	inode_info = ecryptfs_inode_to_private(ctx->page->mapping->host);
 	crypt_stat = &inode_info->crypt_stat;
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
+	if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
 		rc = ecryptfs_copy_page_to_lower(ctx->page, lower_inode,
 						 ctx->param.lower_file);
 		if (rc)
@@ -617,7 +616,7 @@
 	crypt_stat = &(ecryptfs_inode_to_private(
 			       page->mapping->host)->crypt_stat);
 	lower_inode = ecryptfs_inode_to_lower(page->mapping->host);
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
+	if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
 		rc = ecryptfs_do_readpage(file, page, page->index);
 		if (rc)
 			ecryptfs_printk(KERN_ERR, "Error attempting to copy "
@@ -863,7 +862,10 @@
 			ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
 	} else
 		crypt_stat->header_extent_size = PAGE_CACHE_SIZE;
-	crypt_stat->num_header_extents_at_front = 1;
+	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+		crypt_stat->num_header_extents_at_front = 0;
+	else
+		crypt_stat->num_header_extents_at_front = 1;
 }
 
 /**
@@ -879,7 +881,7 @@
 
 	BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE);
 	BUG_ON(crypt_stat->iv_bytes <= 0);
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID)) {
+	if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
 		rc = -EINVAL;
 		ecryptfs_printk(KERN_WARNING, "Session key not valid; "
 				"cannot generate root IV\n");
@@ -896,8 +898,7 @@
 out:
 	if (rc) {
 		memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes);
-		ECRYPTFS_SET_FLAG(crypt_stat->flags,
-				  ECRYPTFS_SECURITY_WARNING);
+		crypt_stat->flags |= ECRYPTFS_SECURITY_WARNING;
 	}
 	return rc;
 }
@@ -905,7 +906,7 @@
 static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat)
 {
 	get_random_bytes(crypt_stat->key, crypt_stat->key_size);
-	ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+	crypt_stat->flags |= ECRYPTFS_KEY_VALID;
 	ecryptfs_compute_root_iv(crypt_stat);
 	if (unlikely(ecryptfs_verbosity > 0)) {
 		ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n");
@@ -915,6 +916,22 @@
 }
 
 /**
+ * ecryptfs_copy_mount_wide_flags_to_inode_flags
+ *
+ * This function propagates the mount-wide flags to individual inode
+ * flags.
+ */
+static void ecryptfs_copy_mount_wide_flags_to_inode_flags(
+	struct ecryptfs_crypt_stat *crypt_stat,
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
+{
+	if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED)
+		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+	if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
+		crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED;
+}
+
+/**
  * ecryptfs_set_default_crypt_stat_vals
  * @crypt_stat
  *
@@ -924,10 +941,12 @@
 	struct ecryptfs_crypt_stat *crypt_stat,
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
 {
+	ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+						      mount_crypt_stat);
 	ecryptfs_set_default_sizes(crypt_stat);
 	strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER);
 	crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES;
-	ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+	crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
 	crypt_stat->file_version = ECRYPTFS_FILE_VERSION;
 	crypt_stat->mount_crypt_stat = mount_crypt_stat;
 }
@@ -967,8 +986,10 @@
 	if (mount_crypt_stat->global_auth_tok) {
 		ecryptfs_printk(KERN_DEBUG, "Initializing context for new "
 				"file using mount_crypt_stat\n");
-		ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
-		ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+		crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
+		crypt_stat->flags |= ECRYPTFS_KEY_VALID;
+		ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+							      mount_crypt_stat);
 		memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++],
 		       mount_crypt_stat->global_auth_tok_sig,
 		       ECRYPTFS_SIG_SIZE_HEX);
@@ -1001,7 +1022,7 @@
  *
  * Returns one if marker found; zero if not found
  */
-int contains_ecryptfs_marker(char *data)
+static int contains_ecryptfs_marker(char *data)
 {
 	u32 m_1, m_2;
 
@@ -1027,7 +1048,8 @@
 /* Add support for additional flags by adding elements here. */
 static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {
 	{0x00000001, ECRYPTFS_ENABLE_HMAC},
-	{0x00000002, ECRYPTFS_ENCRYPTED}
+	{0x00000002, ECRYPTFS_ENCRYPTED},
+	{0x00000004, ECRYPTFS_METADATA_IN_XATTR}
 };
 
 /**
@@ -1050,11 +1072,9 @@
 	for (i = 0; i < ((sizeof(ecryptfs_flag_map)
 			  / sizeof(struct ecryptfs_flag_map_elem))); i++)
 		if (flags & ecryptfs_flag_map[i].file_flag) {
-			ECRYPTFS_SET_FLAG(crypt_stat->flags,
-					  ecryptfs_flag_map[i].local_flag);
+			crypt_stat->flags |= ecryptfs_flag_map[i].local_flag;
 		} else
-			ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
-					    ecryptfs_flag_map[i].local_flag);
+			crypt_stat->flags &= ~(ecryptfs_flag_map[i].local_flag);
 	/* Version is in top 8 bits of the 32-bit flag vector */
 	crypt_stat->file_version = ((flags >> 24) & 0xFF);
 	(*bytes_read) = 4;
@@ -1091,8 +1111,7 @@
 
 	for (i = 0; i < ((sizeof(ecryptfs_flag_map)
 			  / sizeof(struct ecryptfs_flag_map_elem))); i++)
-		if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-					ecryptfs_flag_map[i].local_flag))
+		if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag)
 			flags |= ecryptfs_flag_map[i].file_flag;
 	/* Version is in top 8 bits of the 32-bit flag vector */
 	flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000);
@@ -1187,8 +1206,8 @@
  *
  * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_read_header_region(char *data, struct dentry *dentry,
-				struct vfsmount *mnt)
+static int ecryptfs_read_header_region(char *data, struct dentry *dentry,
+				       struct vfsmount *mnt)
 {
 	struct file *lower_file;
 	mm_segment_t oldfs;
@@ -1217,9 +1236,25 @@
 	return rc;
 }
 
-static void
-write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat,
-		      size_t *written)
+int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
+					     struct vfsmount *mnt)
+{
+	int rc;
+
+	rc = ecryptfs_read_header_region(data, dentry, mnt);
+	if (rc)
+		goto out;
+	if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES))
+		rc = -EINVAL;
+out:
+	return rc;
+}
+
+
+void
+ecryptfs_write_header_metadata(char *virt,
+			       struct ecryptfs_crypt_stat *crypt_stat,
+			       size_t *written)
 {
 	u32 header_extent_size;
 	u16 num_header_extents_at_front;
@@ -1268,9 +1303,9 @@
  *
  * Returns zero on success
  */
-int ecryptfs_write_headers_virt(char *page_virt,
-				struct ecryptfs_crypt_stat *crypt_stat,
-				struct dentry *ecryptfs_dentry)
+static int ecryptfs_write_headers_virt(char *page_virt, size_t *size,
+				       struct ecryptfs_crypt_stat *crypt_stat,
+				       struct dentry *ecryptfs_dentry)
 {
 	int rc;
 	size_t written;
@@ -1281,7 +1316,8 @@
 	offset += written;
 	write_ecryptfs_flags((page_virt + offset), crypt_stat, &written);
 	offset += written;
-	write_header_metadata((page_virt + offset), crypt_stat, &written);
+	ecryptfs_write_header_metadata((page_virt + offset), crypt_stat,
+				       &written);
 	offset += written;
 	rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat,
 					      ecryptfs_dentry, &written,
@@ -1289,11 +1325,70 @@
 	if (rc)
 		ecryptfs_printk(KERN_WARNING, "Error generating key packet "
 				"set; rc = [%d]\n", rc);
+	if (size) {
+		offset += written;
+		*size = offset;
+	}
+	return rc;
+}
+
+static int ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
+					       struct file *lower_file,
+					       char *page_virt)
+{
+	mm_segment_t oldfs;
+	int current_header_page;
+	int header_pages;
+	ssize_t size;
+	int rc = 0;
+
+	lower_file->f_pos = 0;
+	oldfs = get_fs();
+	set_fs(get_ds());
+	size = vfs_write(lower_file, (char __user *)page_virt, PAGE_CACHE_SIZE,
+			 &lower_file->f_pos);
+	if (size < 0) {
+		rc = (int)size;
+		printk(KERN_ERR "Error attempting to write lower page; "
+		       "rc = [%d]\n", rc);
+		set_fs(oldfs);
+		goto out;
+	}
+	header_pages = ((crypt_stat->header_extent_size
+			 * crypt_stat->num_header_extents_at_front)
+			/ PAGE_CACHE_SIZE);
+	memset(page_virt, 0, PAGE_CACHE_SIZE);
+	current_header_page = 1;
+	while (current_header_page < header_pages) {
+		size = vfs_write(lower_file, (char __user *)page_virt,
+				 PAGE_CACHE_SIZE, &lower_file->f_pos);
+		if (size < 0) {
+			rc = (int)size;
+			printk(KERN_ERR "Error attempting to write lower page; "
+			       "rc = [%d]\n", rc);
+			set_fs(oldfs);
+			goto out;
+		}
+		current_header_page++;
+	}
+	set_fs(oldfs);
+out:
+	return rc;
+}
+
+static int ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
+					    struct ecryptfs_crypt_stat *crypt_stat,
+					    char *page_virt, size_t size)
+{
+	int rc;
+
+	rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt,
+			       size, 0);
 	return rc;
 }
 
 /**
- * ecryptfs_write_headers
+ * ecryptfs_write_metadata
  * @lower_file: The lower file struct, which was returned from dentry_open
  *
  * Write the file headers out.  This will likely involve a userspace
@@ -1304,22 +1399,18 @@
  *
  * Returns zero on success; non-zero on error
  */
-int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
-			   struct file *lower_file)
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+			    struct file *lower_file)
 {
-	mm_segment_t oldfs;
 	struct ecryptfs_crypt_stat *crypt_stat;
 	char *page_virt;
-	int current_header_page;
-	int header_pages;
+	size_t size;
 	int rc = 0;
 
 	crypt_stat = &ecryptfs_inode_to_private(
 		ecryptfs_dentry->d_inode)->crypt_stat;
-	if (likely(ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-				       ECRYPTFS_ENCRYPTED))) {
-		if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-					 ECRYPTFS_KEY_VALID)) {
+	if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
+		if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
 			ecryptfs_printk(KERN_DEBUG, "Key is "
 					"invalid; bailing out\n");
 			rc = -EINVAL;
@@ -1338,48 +1429,36 @@
 		rc = -ENOMEM;
 		goto out;
 	}
-
-	rc = ecryptfs_write_headers_virt(page_virt, crypt_stat,
-					 ecryptfs_dentry);
+	rc = ecryptfs_write_headers_virt(page_virt, &size, crypt_stat,
+  					 ecryptfs_dentry);
 	if (unlikely(rc)) {
 		ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n");
 		memset(page_virt, 0, PAGE_CACHE_SIZE);
 		goto out_free;
 	}
-	ecryptfs_printk(KERN_DEBUG,
-			"Writing key packet set to underlying file\n");
-	lower_file->f_pos = 0;
-	oldfs = get_fs();
-	set_fs(get_ds());
-	ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->"
-			"write() w/ header page; lower_file->f_pos = "
-			"[0x%.16x]\n", lower_file->f_pos);
-	lower_file->f_op->write(lower_file, (char __user *)page_virt,
-				PAGE_CACHE_SIZE, &lower_file->f_pos);
-	header_pages = ((crypt_stat->header_extent_size
-			 * crypt_stat->num_header_extents_at_front)
-			/ PAGE_CACHE_SIZE);
-	memset(page_virt, 0, PAGE_CACHE_SIZE);
-	current_header_page = 1;
-	while (current_header_page < header_pages) {
-		ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->"
-				"write() w/ zero'd page; lower_file->f_pos = "
-				"[0x%.16x]\n", lower_file->f_pos);
-		lower_file->f_op->write(lower_file, (char __user *)page_virt,
-					PAGE_CACHE_SIZE, &lower_file->f_pos);
-		current_header_page++;
+	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+		rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry,
+						      crypt_stat, page_virt,
+						      size);
+	else
+		rc = ecryptfs_write_metadata_to_contents(crypt_stat, lower_file,
+							 page_virt);
+	if (rc) {
+		printk(KERN_ERR "Error writing metadata out to lower file; "
+		       "rc = [%d]\n", rc);
+		goto out_free;
 	}
-	set_fs(oldfs);
-	ecryptfs_printk(KERN_DEBUG,
-			"Done writing key packet set to underlying file.\n");
 out_free:
 	kmem_cache_free(ecryptfs_header_cache_0, page_virt);
 out:
 	return rc;
 }
 
+#define ECRYPTFS_DONT_VALIDATE_HEADER_SIZE 0
+#define ECRYPTFS_VALIDATE_HEADER_SIZE 1
 static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
-				 char *virt, int *bytes_read)
+				 char *virt, int *bytes_read,
+				 int validate_header_size)
 {
 	int rc = 0;
 	u32 header_extent_size;
@@ -1394,9 +1473,10 @@
 	crypt_stat->num_header_extents_at_front =
 		(int)num_header_extents_at_front;
 	(*bytes_read) = 6;
-	if ((crypt_stat->header_extent_size
-	     * crypt_stat->num_header_extents_at_front)
-	    < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
+	if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
+	    && ((crypt_stat->header_extent_size
+		 * crypt_stat->num_header_extents_at_front)
+		< ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
 		rc = -EINVAL;
 		ecryptfs_printk(KERN_WARNING, "Invalid header extent size: "
 				"[%d]\n", crypt_stat->header_extent_size);
@@ -1427,7 +1507,8 @@
  */
 static int ecryptfs_read_headers_virt(char *page_virt,
 				      struct ecryptfs_crypt_stat *crypt_stat,
-				      struct dentry *ecryptfs_dentry)
+				      struct dentry *ecryptfs_dentry,
+				      int validate_header_size)
 {
 	int rc = 0;
 	int offset;
@@ -1461,7 +1542,7 @@
 	offset += bytes_read;
 	if (crypt_stat->file_version >= 1) {
 		rc = parse_header_metadata(crypt_stat, (page_virt + offset),
-					   &bytes_read);
+					   &bytes_read, validate_header_size);
 		if (rc) {
 			ecryptfs_printk(KERN_WARNING, "Error reading header "
 					"metadata; rc = [%d]\n", rc);
@@ -1476,12 +1557,60 @@
 }
 
 /**
- * ecryptfs_read_headers
+ * ecryptfs_read_xattr_region
+ *
+ * Attempts to read the crypto metadata from the extended attribute
+ * region of the lower file.
+ */
+int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry)
+{
+	ssize_t size;
+	int rc = 0;
+
+	size = ecryptfs_getxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME,
+				 page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE);
+	if (size < 0) {
+		printk(KERN_DEBUG "Error attempting to read the [%s] "
+		       "xattr from the lower file; return value = [%zd]\n",
+		       ECRYPTFS_XATTR_NAME, size);
+		rc = -EINVAL;
+		goto out;
+	}
+out:
+	return rc;
+}
+
+int ecryptfs_read_and_validate_xattr_region(char *page_virt,
+					    struct dentry *ecryptfs_dentry)
+{
+	int rc;
+
+	rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_dentry);
+	if (rc)
+		goto out;
+	if (!contains_ecryptfs_marker(page_virt	+ ECRYPTFS_FILE_SIZE_BYTES)) {
+		printk(KERN_WARNING "Valid data found in [%s] xattr, but "
+			"the marker is invalid\n", ECRYPTFS_XATTR_NAME);
+		rc = -EINVAL;
+	}
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_read_metadata
+ *
+ * Common entry point for reading file metadata. From here, we could
+ * retrieve the header information from the header region of the file,
+ * the xattr region of the file, or some other repostory that is
+ * stored separately from the file itself. The current implementation
+ * supports retrieving the metadata information from the file contents
+ * and from the xattr region.
  *
  * Returns zero if valid headers found and parsed; non-zero otherwise
  */
-int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
-			  struct file *lower_file)
+int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
+			   struct file *lower_file)
 {
 	int rc = 0;
 	char *page_virt = NULL;
@@ -1489,7 +1618,12 @@
 	ssize_t bytes_read;
 	struct ecryptfs_crypt_stat *crypt_stat =
 	    &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+		&ecryptfs_superblock_to_private(
+			ecryptfs_dentry->d_sb)->mount_crypt_stat;
 
+	ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,
+						      mount_crypt_stat);
 	/* Read the first page from the underlying file */
 	page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, GFP_USER);
 	if (!page_virt) {
@@ -1510,11 +1644,36 @@
 		goto out;
 	}
 	rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
-					ecryptfs_dentry);
+					ecryptfs_dentry,
+					ECRYPTFS_VALIDATE_HEADER_SIZE);
 	if (rc) {
-		ecryptfs_printk(KERN_DEBUG, "Valid eCryptfs headers not "
-				"found\n");
-		rc = -EINVAL;
+		rc = ecryptfs_read_xattr_region(page_virt,
+						ecryptfs_dentry);
+		if (rc) {
+			printk(KERN_DEBUG "Valid eCryptfs headers not found in "
+			       "file header region or xattr region\n");
+			rc = -EINVAL;
+			goto out;
+		}
+		rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
+						ecryptfs_dentry,
+						ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);
+		if (rc) {
+			printk(KERN_DEBUG "Valid eCryptfs headers not found in "
+			       "file xattr region either\n");
+			rc = -EINVAL;
+		}
+		if (crypt_stat->mount_crypt_stat->flags
+		    & ECRYPTFS_XATTR_METADATA_ENABLED) {
+			crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+		} else {
+			printk(KERN_WARNING "Attempt to access file with "
+			       "crypto metadata only in the extended attribute "
+			       "region, but eCryptfs was mounted without "
+			       "xattr support enabled. eCryptfs will not treat "
+			       "this like an encrypted file.\n");
+			rc = -EINVAL;
+		}
 	}
 out:
 	if (page_virt) {
diff --git a/fs/ecryptfs/debug.c b/fs/ecryptfs/debug.c
index 61f8e89..434c7ef 100644
--- a/fs/ecryptfs/debug.c
+++ b/fs/ecryptfs/debug.c
@@ -36,7 +36,7 @@
 
 	ecryptfs_printk(KERN_DEBUG, "Auth tok at mem loc [%p]:\n",
 			auth_tok);
-	if (ECRYPTFS_CHECK_FLAG(auth_tok->flags, ECRYPTFS_PRIVATE_KEY)) {
+	if (auth_tok->flags & ECRYPTFS_PRIVATE_KEY) {
 		ecryptfs_printk(KERN_DEBUG, " * private key type\n");
 		ecryptfs_printk(KERN_DEBUG, " * (NO PRIVATE KEY SUPPORT "
 				"IN ECRYPTFS VERSION 0.1)\n");
@@ -46,8 +46,8 @@
 				ECRYPTFS_SALT_SIZE);
 		salt[ECRYPTFS_SALT_SIZE * 2] = '\0';
 		ecryptfs_printk(KERN_DEBUG, " * salt = [%s]\n", salt);
-		if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags,
-					ECRYPTFS_PERSISTENT_PASSWORD)) {
+		if (auth_tok->token.password.flags &
+		    ECRYPTFS_PERSISTENT_PASSWORD) {
 			ecryptfs_printk(KERN_DEBUG, " * persistent\n");
 		}
 		memcpy(sig, auth_tok->token.password.signature,
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 0f89710..b3609b7 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -4,8 +4,10 @@
  *
  * Copyright (C) 1997-2003 Erez Zadok
  * Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
+ *              Trevor S. Highland <trevor.highland@gmail.com>
+ *              Tyler Hicks <tyhicks@ou.edu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -31,22 +33,25 @@
 #include <linux/fs_stack.h>
 #include <linux/namei.h>
 #include <linux/scatterlist.h>
+#include <linux/hash.h>
 
 /* Version verification for shared data structures w/ userspace */
 #define ECRYPTFS_VERSION_MAJOR 0x00
 #define ECRYPTFS_VERSION_MINOR 0x04
-#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x01
+#define ECRYPTFS_SUPPORTED_FILE_VERSION 0x02
 /* These flags indicate which features are supported by the kernel
  * module; userspace tools such as the mount helper read
  * ECRYPTFS_VERSIONING_MASK from a sysfs handle in order to determine
  * how to behave. */
-#define ECRYPTFS_VERSIONING_PASSPHRASE 0x00000001
-#define ECRYPTFS_VERSIONING_PUBKEY 0x00000002
+#define ECRYPTFS_VERSIONING_PASSPHRASE            0x00000001
+#define ECRYPTFS_VERSIONING_PUBKEY                0x00000002
 #define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
-#define ECRYPTFS_VERSIONING_POLICY 0x00000008
+#define ECRYPTFS_VERSIONING_POLICY                0x00000008
+#define ECRYPTFS_VERSIONING_XATTR                 0x00000010
 #define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
-                                  | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH)
-
+				  | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
+				  | ECRYPTFS_VERSIONING_PUBKEY \
+				  | ECRYPTFS_VERSIONING_XATTR)
 #define ECRYPTFS_MAX_PASSWORD_LENGTH 64
 #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
 #define ECRYPTFS_SALT_SIZE 8
@@ -60,10 +65,25 @@
 #define ECRYPTFS_MAX_KEY_BYTES 64
 #define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512
 #define ECRYPTFS_DEFAULT_IV_BYTES 16
-#define ECRYPTFS_FILE_VERSION 0x01
+#define ECRYPTFS_FILE_VERSION 0x02
 #define ECRYPTFS_DEFAULT_HEADER_EXTENT_SIZE 8192
 #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
 #define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192
+#define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32
+#define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ
+#define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3)
+#define ECRYPTFS_NLMSG_HELO 100
+#define ECRYPTFS_NLMSG_QUIT 101
+#define ECRYPTFS_NLMSG_REQUEST 102
+#define ECRYPTFS_NLMSG_RESPONSE 103
+#define ECRYPTFS_MAX_PKI_NAME_BYTES 16
+#define ECRYPTFS_DEFAULT_NUM_USERS 4
+#define ECRYPTFS_MAX_NUM_USERS 32768
+#define ECRYPTFS_TRANSPORT_NETLINK 0
+#define ECRYPTFS_TRANSPORT_CONNECTOR 1
+#define ECRYPTFS_TRANSPORT_RELAYFS 2
+#define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_NETLINK
+#define ECRYPTFS_XATTR_NAME "user.ecryptfs"
 
 #define RFC2440_CIPHER_DES3_EDE 0x02
 #define RFC2440_CIPHER_CAST_5 0x03
@@ -74,9 +94,7 @@
 #define RFC2440_CIPHER_TWOFISH 0x0a
 #define RFC2440_CIPHER_CAST_6 0x0b
 
-#define ECRYPTFS_SET_FLAG(flag_bit_vector, flag) (flag_bit_vector |= (flag))
-#define ECRYPTFS_CLEAR_FLAG(flag_bit_vector, flag) (flag_bit_vector &= ~(flag))
-#define ECRYPTFS_CHECK_FLAG(flag_bit_vector, flag) (flag_bit_vector & (flag))
+#define RFC2440_CIPHER_RSA 0x01
 
 /**
  * For convenience, we may need to pass around the encrypted session
@@ -114,6 +132,14 @@
 
 enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY};
 
+struct ecryptfs_private_key {
+	u32 key_size;
+	u32 data_len;
+	u8 signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
+	char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1];
+	u8 data[];
+};
+
 /* May be a password or a private key */
 struct ecryptfs_auth_tok {
 	u16 version; /* 8-bit major and 8-bit minor */
@@ -123,7 +149,7 @@
 	u8 reserved[32];
 	union {
 		struct ecryptfs_password password;
-		/* Private key is in future eCryptfs releases */
+		struct ecryptfs_private_key private_key;
 	} token;
 } __attribute__ ((packed));
 
@@ -177,8 +203,13 @@
 #define ECRYPTFS_DEFAULT_CIPHER "aes"
 #define ECRYPTFS_DEFAULT_KEY_BYTES 16
 #define ECRYPTFS_DEFAULT_HASH "md5"
+#define ECRYPTFS_TAG_1_PACKET_TYPE 0x01
 #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
 #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED
+#define ECRYPTFS_TAG_64_PACKET_TYPE 0x40
+#define ECRYPTFS_TAG_65_PACKET_TYPE 0x41
+#define ECRYPTFS_TAG_66_PACKET_TYPE 0x42
+#define ECRYPTFS_TAG_67_PACKET_TYPE 0x43
 #define MD5_DIGEST_SIZE 16
 
 /**
@@ -195,6 +226,8 @@
 #define ECRYPTFS_ENABLE_HMAC        0x00000020
 #define ECRYPTFS_ENCRYPT_IV_PAGES   0x00000040
 #define ECRYPTFS_KEY_VALID          0x00000080
+#define ECRYPTFS_METADATA_IN_XATTR  0x00000100
+#define ECRYPTFS_VIEW_AS_ENCRYPTED  0x00000200
 	u32 flags;
 	unsigned int file_version;
 	size_t iv_bytes;
@@ -241,6 +274,8 @@
 struct ecryptfs_mount_crypt_stat {
 	/* Pointers to memory we do not own, do not free these */
 #define ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED 0x00000001
+#define ECRYPTFS_XATTR_METADATA_ENABLED        0x00000002
+#define ECRYPTFS_ENCRYPTED_VIEW_ENABLED        0x00000004
 	u32 flags;
 	struct ecryptfs_auth_tok *global_auth_tok;
 	struct key *global_auth_tok_key;
@@ -271,6 +306,33 @@
 	struct ecryptfs_auth_tok auth_tok;
 };
 
+struct ecryptfs_message {
+	u32 index;
+	u32 data_len;
+	u8 data[];
+};
+
+struct ecryptfs_msg_ctx {
+#define ECRYPTFS_MSG_CTX_STATE_FREE      0x0001
+#define ECRYPTFS_MSG_CTX_STATE_PENDING   0x0002
+#define ECRYPTFS_MSG_CTX_STATE_DONE      0x0003
+	u32 state;
+	unsigned int index;
+	unsigned int counter;
+	struct ecryptfs_message *msg;
+	struct task_struct *task;
+	struct list_head node;
+	struct mutex mux;
+};
+
+extern unsigned int ecryptfs_transport;
+
+struct ecryptfs_daemon_id {
+	pid_t pid;
+	uid_t uid;
+	struct hlist_node id_chain;
+};
+
 static inline struct ecryptfs_file_info *
 ecryptfs_file_to_private(struct file *file)
 {
@@ -384,13 +446,16 @@
 
 extern const struct file_operations ecryptfs_main_fops;
 extern const struct file_operations ecryptfs_dir_fops;
-extern struct inode_operations ecryptfs_main_iops;
-extern struct inode_operations ecryptfs_dir_iops;
-extern struct inode_operations ecryptfs_symlink_iops;
-extern struct super_operations ecryptfs_sops;
+extern const struct inode_operations ecryptfs_main_iops;
+extern const struct inode_operations ecryptfs_dir_iops;
+extern const struct inode_operations ecryptfs_symlink_iops;
+extern const struct super_operations ecryptfs_sops;
 extern struct dentry_operations ecryptfs_dops;
 extern struct address_space_operations ecryptfs_aops;
 extern int ecryptfs_verbosity;
+extern unsigned int ecryptfs_message_buf_len;
+extern signed long ecryptfs_message_wait_timeout;
+extern unsigned int ecryptfs_number_of_users;
 
 extern struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
 extern struct kmem_cache *ecryptfs_file_info_cache;
@@ -400,6 +465,7 @@
 extern struct kmem_cache *ecryptfs_header_cache_0;
 extern struct kmem_cache *ecryptfs_header_cache_1;
 extern struct kmem_cache *ecryptfs_header_cache_2;
+extern struct kmem_cache *ecryptfs_xattr_cache;
 extern struct kmem_cache *ecryptfs_lower_page_cache;
 
 int ecryptfs_interpose(struct dentry *hidden_dentry,
@@ -426,9 +492,13 @@
 int ecryptfs_crypto_api_algify_cipher_name(char **algified_name,
 					   char *cipher_name,
 					   char *chaining_modifier);
-int ecryptfs_write_inode_size_to_header(struct file *lower_file,
-					struct inode *lower_inode,
-					struct inode *inode);
+#define ECRYPTFS_LOWER_I_MUTEX_NOT_HELD 0
+#define ECRYPTFS_LOWER_I_MUTEX_HELD 1
+int ecryptfs_write_inode_size_to_metadata(struct file *lower_file,
+					  struct inode *lower_inode,
+					  struct inode *inode,
+					  struct dentry *ecryptfs_dentry,
+					  int lower_i_mutex_held);
 int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
 			    struct file *lower_file,
 			    unsigned long lower_page_index, int byte_offset,
@@ -441,26 +511,20 @@
 				struct file *lower_file);
 int ecryptfs_do_readpage(struct file *file, struct page *page,
 			 pgoff_t lower_page_index);
-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
-				     char **lower_virt,
-				     struct inode *lower_inode,
-				     unsigned long lower_page_index);
 int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
 					      struct inode *lower_inode,
 					      struct writeback_control *wbc);
 int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx);
 int ecryptfs_decrypt_page(struct file *file, struct page *page);
-int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+			    struct file *lower_file);
+int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry,
 			   struct file *lower_file);
-int ecryptfs_write_headers_virt(char *page_virt,
-				struct ecryptfs_crypt_stat *crypt_stat,
-				struct dentry *ecryptfs_dentry);
-int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
-			  struct file *lower_file);
 int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry);
-int contains_ecryptfs_marker(char *data);
-int ecryptfs_read_header_region(char *data, struct dentry *dentry,
-				struct vfsmount *mnt);
+int ecryptfs_read_and_validate_header_region(char *data, struct dentry *dentry,
+					     struct vfsmount *mnt);
+int ecryptfs_read_and_validate_xattr_region(char *page_virt,
+					    struct dentry *ecryptfs_dentry);
 u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat);
 int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code);
 void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat);
@@ -483,5 +547,37 @@
 			     struct dentry *lower_dentry,
 			     struct vfsmount *lower_mnt, int flags);
 int ecryptfs_close_lower_file(struct file *lower_file);
+ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
+			  size_t size);
+int
+ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		  size_t size, int flags);
+int ecryptfs_read_xattr_region(char *page_virt, struct dentry *ecryptfs_dentry);
+int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid);
+int ecryptfs_process_quit(uid_t uid, pid_t pid);
+int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
+			      pid_t pid, u32 seq);
+int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+			  struct ecryptfs_msg_ctx **msg_ctx);
+int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
+			       struct ecryptfs_message **emsg);
+int ecryptfs_init_messaging(unsigned int transport);
+void ecryptfs_release_messaging(unsigned int transport);
+
+int ecryptfs_send_netlink(char *data, int data_len,
+			  struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+			  u16 msg_flags, pid_t daemon_pid);
+int ecryptfs_init_netlink(void);
+void ecryptfs_release_netlink(void);
+
+int ecryptfs_send_connector(char *data, int data_len,
+			    struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+			    u16 msg_flags, pid_t daemon_pid);
+int ecryptfs_init_connector(void);
+void ecryptfs_release_connector(void);
+void
+ecryptfs_write_header_metadata(char *virt,
+			       struct ecryptfs_crypt_stat *crypt_stat,
+			       size_t *written);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 779c347..bd969ad 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1997-2004 Erez Zadok
  * Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
  *   		Michael C. Thompson <mcthomps@us.ibm.com>
  *
@@ -250,6 +250,17 @@
 	struct ecryptfs_file_info *file_info;
 	int lower_flags;
 
+	mount_crypt_stat = &ecryptfs_superblock_to_private(
+		ecryptfs_dentry->d_sb)->mount_crypt_stat;
+	if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
+	    && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR)
+		|| (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC)
+		|| (file->f_flags & O_APPEND))) {
+		printk(KERN_WARNING "Mount has encrypted view enabled; "
+		       "files may only be read\n");
+		rc = -EPERM;
+		goto out;
+	}
 	/* Released in ecryptfs_release or end of function if failure */
 	file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL);
 	ecryptfs_set_file_private(file, file_info);
@@ -261,14 +272,12 @@
 	}
 	lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
 	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
-	mount_crypt_stat = &ecryptfs_superblock_to_private(
-		ecryptfs_dentry->d_sb)->mount_crypt_stat;
 	mutex_lock(&crypt_stat->cs_mutex);
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) {
+	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)) {
 		ecryptfs_printk(KERN_DEBUG, "Setting flags for stat...\n");
 		/* Policy code enabled in future release */
-		ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED);
-		ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+		crypt_stat->flags |= ECRYPTFS_POLICY_APPLIED;
+		crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
 	}
 	mutex_unlock(&crypt_stat->cs_mutex);
 	lower_flags = file->f_flags;
@@ -288,31 +297,14 @@
 	lower_inode = lower_dentry->d_inode;
 	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
 		ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
-		ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
 		rc = 0;
 		goto out;
 	}
 	mutex_lock(&crypt_stat->cs_mutex);
-	if (i_size_read(lower_inode) < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
-		if (!(mount_crypt_stat->flags
-		      & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
-			rc = -EIO;
-			printk(KERN_WARNING "Attempt to read file that is "
-			       "not in a valid eCryptfs format, and plaintext "
-			       "passthrough mode is not enabled; returning "
-			       "-EIO\n");
-			mutex_unlock(&crypt_stat->cs_mutex);
-			goto out_puts;
-		}
-		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
-		rc = 0;
-		mutex_unlock(&crypt_stat->cs_mutex);
-		goto out;
-	} else if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-					ECRYPTFS_POLICY_APPLIED)
-		   || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
-					   ECRYPTFS_KEY_VALID)) {
-		rc = ecryptfs_read_headers(ecryptfs_dentry, lower_file);
+	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
+	    || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
+		rc = ecryptfs_read_metadata(ecryptfs_dentry, lower_file);
 		if (rc) {
 			ecryptfs_printk(KERN_DEBUG,
 					"Valid headers not found\n");
@@ -326,9 +318,8 @@
 				mutex_unlock(&crypt_stat->cs_mutex);
 				goto out_puts;
 			}
-			ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
-					    ECRYPTFS_ENCRYPTED);
 			rc = 0;
+			crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
 			mutex_unlock(&crypt_stat->cs_mutex);
 			goto out;
 		}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index d4f02f3..9fa7e0b 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1997-2004 Erez Zadok
  * Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *              Michael C. Thompsion <mcthomps@us.ibm.com>
  *
@@ -161,17 +161,17 @@
 	ecryptfs_set_file_lower(&fake_file, lower_file);
 	rc = ecryptfs_fill_zeros(&fake_file, 1);
 	if (rc) {
-		ECRYPTFS_SET_FLAG(
-			ecryptfs_inode_to_private(inode)->crypt_stat.flags,
-			ECRYPTFS_SECURITY_WARNING);
+		ecryptfs_inode_to_private(inode)->crypt_stat.flags |=
+			ECRYPTFS_SECURITY_WARNING;
 		ecryptfs_printk(KERN_WARNING, "Error attempting to fill zeros "
 				"in file; rc = [%d]\n", rc);
 		goto out;
 	}
 	i_size_write(inode, 0);
-	ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode);
-	ECRYPTFS_SET_FLAG(ecryptfs_inode_to_private(inode)->crypt_stat.flags,
-			  ECRYPTFS_NEW_FILE);
+	ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode, inode,
+					      ecryptfs_dentry,
+					      ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
+	ecryptfs_inode_to_private(inode)->crypt_stat.flags |= ECRYPTFS_NEW_FILE;
 out:
 	return rc;
 }
@@ -199,7 +199,7 @@
 			lower_dentry->d_name.name);
 	inode = ecryptfs_dentry->d_inode;
 	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
-	lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR;
+	lower_flags = ((O_CREAT | O_TRUNC) & O_ACCMODE) | O_RDWR;
 #if BITS_PER_LONG != 32
 	lower_flags |= O_LARGEFILE;
 #endif
@@ -214,10 +214,10 @@
 	lower_inode = lower_dentry->d_inode;
 	if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
 		ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
-		ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
+		crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
 		goto out_fput;
 	}
-	ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
+	crypt_stat->flags |= ECRYPTFS_NEW_FILE;
 	ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n");
 	rc = ecryptfs_new_file_context(ecryptfs_dentry);
 	if (rc) {
@@ -225,7 +225,7 @@
 				"context\n");
 		goto out_fput;
 	}
-	rc = ecryptfs_write_headers(ecryptfs_dentry, lower_file);
+	rc = ecryptfs_write_metadata(ecryptfs_dentry, lower_file);
 	if (rc) {
 		ecryptfs_printk(KERN_DEBUG, "Error writing headers\n");
 		goto out_fput;
@@ -287,6 +287,7 @@
 	char *encoded_name;
 	unsigned int encoded_namelen;
 	struct ecryptfs_crypt_stat *crypt_stat = NULL;
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
 	char *page_virt = NULL;
 	struct inode *lower_inode;
 	u64 file_size;
@@ -362,32 +363,43 @@
 	}
 	/* Released in this function */
 	page_virt = kmem_cache_zalloc(ecryptfs_header_cache_2,
-				     GFP_USER);
+				      GFP_USER);
 	if (!page_virt) {
 		rc = -ENOMEM;
 		ecryptfs_printk(KERN_ERR,
 				"Cannot ecryptfs_kmalloc a page\n");
 		goto out_dput;
 	}
-
-	rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt);
 	crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
-	if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED))
+	if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED))
 		ecryptfs_set_default_sizes(crypt_stat);
+	rc = ecryptfs_read_and_validate_header_region(page_virt, lower_dentry,
+						      nd->mnt);
 	if (rc) {
-		rc = 0;
-		ecryptfs_printk(KERN_WARNING, "Error reading header region;"
-				" assuming unencrypted\n");
-	} else {
-		if (!contains_ecryptfs_marker(page_virt
-					      + ECRYPTFS_FILE_SIZE_BYTES)) {
+		rc = ecryptfs_read_and_validate_xattr_region(page_virt, dentry);
+		if (rc) {
+			printk(KERN_DEBUG "Valid metadata not found in header "
+			       "region or xattr region; treating file as "
+			       "unencrypted\n");
+			rc = 0;
 			kmem_cache_free(ecryptfs_header_cache_2, page_virt);
 			goto out;
 		}
+		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
+	}
+	mount_crypt_stat = &ecryptfs_superblock_to_private(
+		dentry->d_sb)->mount_crypt_stat;
+	if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
+		if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+			file_size = (crypt_stat->header_extent_size
+				     + i_size_read(lower_dentry->d_inode));
+		else
+			file_size = i_size_read(lower_dentry->d_inode);
+	} else {
 		memcpy(&file_size, page_virt, sizeof(file_size));
 		file_size = be64_to_cpu(file_size);
-		i_size_write(dentry->d_inode, (loff_t)file_size);
 	}
+	i_size_write(dentry->d_inode, (loff_t)file_size);
 	kmem_cache_free(ecryptfs_header_cache_2, page_virt);
 	goto out;
 
@@ -781,20 +793,26 @@
 			goto out_fput;
 		}
 		i_size_write(inode, new_length);
-		rc = ecryptfs_write_inode_size_to_header(lower_file,
-							 lower_dentry->d_inode,
-							 inode);
+		rc = ecryptfs_write_inode_size_to_metadata(
+			lower_file, lower_dentry->d_inode, inode, dentry,
+			ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
 		if (rc) {
-			ecryptfs_printk(KERN_ERR,
-					"Problem with ecryptfs_write"
-					"_inode_size\n");
+			printk(KERN_ERR	"Problem with "
+			       "ecryptfs_write_inode_size_to_metadata; "
+			       "rc = [%d]\n", rc);
 			goto out_fput;
 		}
 	} else { /* new_length < i_size_read(inode) */
 		vmtruncate(inode, new_length);
-		ecryptfs_write_inode_size_to_header(lower_file,
-						    lower_dentry->d_inode,
-						    inode);
+		rc = ecryptfs_write_inode_size_to_metadata(
+			lower_file, lower_dentry->d_inode, inode, dentry,
+			ECRYPTFS_LOWER_I_MUTEX_NOT_HELD);
+		if (rc) {
+			printk(KERN_ERR	"Problem with "
+			       "ecryptfs_write_inode_size_to_metadata; "
+			       "rc = [%d]\n", rc);
+			goto out_fput;
+		}
 		/* We are reducing the size of the ecryptfs file, and need to
 		 * know if we need to reduce the size of the lower file. */
 		lower_size_before_truncate =
@@ -881,7 +899,7 @@
 	return rc;
 }
 
-static int
+int
 ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		  size_t size, int flags)
 {
@@ -901,7 +919,7 @@
 	return rc;
 }
 
-static ssize_t
+ssize_t
 ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
 		  size_t size)
 {
@@ -971,7 +989,7 @@
 	return 0;
 }
 
-struct inode_operations ecryptfs_symlink_iops = {
+const struct inode_operations ecryptfs_symlink_iops = {
 	.readlink = ecryptfs_readlink,
 	.follow_link = ecryptfs_follow_link,
 	.put_link = ecryptfs_put_link,
@@ -983,7 +1001,7 @@
 	.removexattr = ecryptfs_removexattr
 };
 
-struct inode_operations ecryptfs_dir_iops = {
+const struct inode_operations ecryptfs_dir_iops = {
 	.create = ecryptfs_create,
 	.lookup = ecryptfs_lookup,
 	.link = ecryptfs_link,
@@ -1001,7 +1019,7 @@
 	.removexattr = ecryptfs_removexattr
 };
 
-struct inode_operations ecryptfs_main_iops = {
+const struct inode_operations ecryptfs_main_iops = {
 	.permission = ecryptfs_permission,
 	.setattr = ecryptfs_setattr,
 	.setxattr = ecryptfs_setxattr,
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 80bccd5..c209f67 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -7,6 +7,7 @@
  * Copyright (C) 2004-2006 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
  *              Michael C. Thompson <mcthomps@us.ibm.com>
+ *              Trevor S. Highland <trevor.highland@gmail.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -64,26 +65,6 @@
 	return rc;
 }
 
-static void wipe_auth_tok_list(struct list_head *auth_tok_list_head)
-{
-	struct list_head *walker;
-	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
-
-	walker = auth_tok_list_head->next;
-	while (walker != auth_tok_list_head) {
-		auth_tok_list_item =
-		    list_entry(walker, struct ecryptfs_auth_tok_list_item,
-			       list);
-		walker = auth_tok_list_item->list.next;
-		memset(auth_tok_list_item, 0,
-		       sizeof(struct ecryptfs_auth_tok_list_item));
-		kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
-				auth_tok_list_item);
-	}
-}
-
-struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
-
 /**
  * parse_packet_length
  * @data: Pointer to memory containing length at offset
@@ -102,12 +83,12 @@
 	(*size) = 0;
 	if (data[0] < 192) {
 		/* One-byte length */
-		(*size) = data[0];
+		(*size) = (unsigned char)data[0];
 		(*length_size) = 1;
 	} else if (data[0] < 224) {
 		/* Two-byte length */
-		(*size) = ((data[0] - 192) * 256);
-		(*size) += (data[1] + 192);
+		(*size) = (((unsigned char)(data[0]) - 192) * 256);
+		(*size) += ((unsigned char)(data[1]) + 192);
 		(*length_size) = 2;
 	} else if (data[0] == 255) {
 		/* Five-byte length; we're not supposed to see this */
@@ -154,6 +135,499 @@
 	return rc;
 }
 
+static int
+write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key,
+		    char **packet, size_t *packet_len)
+{
+	size_t i = 0;
+	size_t data_len;
+	size_t packet_size_len;
+	char *message;
+	int rc;
+
+	/*
+	 *              ***** TAG 64 Packet Format *****
+	 *    | Content Type                       | 1 byte       |
+	 *    | Key Identifier Size                | 1 or 2 bytes |
+	 *    | Key Identifier                     | arbitrary    |
+	 *    | Encrypted File Encryption Key Size | 1 or 2 bytes |
+	 *    | Encrypted File Encryption Key      | arbitrary    |
+	 */
+	data_len = (5 + ECRYPTFS_SIG_SIZE_HEX
+		    + session_key->encrypted_key_size);
+	*packet = kmalloc(data_len, GFP_KERNEL);
+	message = *packet;
+	if (!message) {
+		ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE;
+	rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+				 &packet_size_len);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	i += packet_size_len;
+	memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
+	i += ECRYPTFS_SIG_SIZE_HEX;
+	rc = write_packet_length(&message[i], session_key->encrypted_key_size,
+				 &packet_size_len);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	i += packet_size_len;
+	memcpy(&message[i], session_key->encrypted_key,
+	       session_key->encrypted_key_size);
+	i += session_key->encrypted_key_size;
+	*packet_len = i;
+out:
+	return rc;
+}
+
+static int
+parse_tag_65_packet(struct ecryptfs_session_key *session_key, u16 *cipher_code,
+		    struct ecryptfs_message *msg)
+{
+	size_t i = 0;
+	char *data;
+	size_t data_len;
+	size_t m_size;
+	size_t message_len;
+	u16 checksum = 0;
+	u16 expected_checksum = 0;
+	int rc;
+
+	/*
+	 *              ***** TAG 65 Packet Format *****
+	 *         | Content Type             | 1 byte       |
+	 *         | Status Indicator         | 1 byte       |
+	 *         | File Encryption Key Size | 1 or 2 bytes |
+	 *         | File Encryption Key      | arbitrary    |
+	 */
+	message_len = msg->data_len;
+	data = msg->data;
+	if (message_len < 4) {
+		rc = -EIO;
+		goto out;
+	}
+	if (data[i++] != ECRYPTFS_TAG_65_PACKET_TYPE) {
+		ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_65\n");
+		rc = -EIO;
+		goto out;
+	}
+	if (data[i++]) {
+		ecryptfs_printk(KERN_ERR, "Status indicator has non-zero value "
+				"[%d]\n", data[i-1]);
+		rc = -EIO;
+		goto out;
+	}
+	rc = parse_packet_length(&data[i], &m_size, &data_len);
+	if (rc) {
+		ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+				"rc = [%d]\n", rc);
+		goto out;
+	}
+	i += data_len;
+	if (message_len < (i + m_size)) {
+		ecryptfs_printk(KERN_ERR, "The received netlink message is "
+				"shorter than expected\n");
+		rc = -EIO;
+		goto out;
+	}
+	if (m_size < 3) {
+		ecryptfs_printk(KERN_ERR,
+				"The decrypted key is not long enough to "
+				"include a cipher code and checksum\n");
+		rc = -EIO;
+		goto out;
+	}
+	*cipher_code = data[i++];
+	/* The decrypted key includes 1 byte cipher code and 2 byte checksum */
+	session_key->decrypted_key_size = m_size - 3;
+	if (session_key->decrypted_key_size > ECRYPTFS_MAX_KEY_BYTES) {
+		ecryptfs_printk(KERN_ERR, "key_size [%d] larger than "
+				"the maximum key size [%d]\n",
+				session_key->decrypted_key_size,
+				ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
+		rc = -EIO;
+		goto out;
+	}
+	memcpy(session_key->decrypted_key, &data[i],
+	       session_key->decrypted_key_size);
+	i += session_key->decrypted_key_size;
+	expected_checksum += (unsigned char)(data[i++]) << 8;
+	expected_checksum += (unsigned char)(data[i++]);
+	for (i = 0; i < session_key->decrypted_key_size; i++)
+		checksum += session_key->decrypted_key[i];
+	if (expected_checksum != checksum) {
+		ecryptfs_printk(KERN_ERR, "Invalid checksum for file "
+				"encryption  key; expected [%x]; calculated "
+				"[%x]\n", expected_checksum, checksum);
+		rc = -EIO;
+	}
+out:
+	return rc;
+}
+
+
+static int
+write_tag_66_packet(char *signature, size_t cipher_code,
+		    struct ecryptfs_crypt_stat *crypt_stat, char **packet,
+		    size_t *packet_len)
+{
+	size_t i = 0;
+	size_t j;
+	size_t data_len;
+	size_t checksum = 0;
+	size_t packet_size_len;
+	char *message;
+	int rc;
+
+	/*
+	 *              ***** TAG 66 Packet Format *****
+	 *         | Content Type             | 1 byte       |
+	 *         | Key Identifier Size      | 1 or 2 bytes |
+	 *         | Key Identifier           | arbitrary    |
+	 *         | File Encryption Key Size | 1 or 2 bytes |
+	 *         | File Encryption Key      | arbitrary    |
+	 */
+	data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size);
+	*packet = kmalloc(data_len, GFP_KERNEL);
+	message = *packet;
+	if (!message) {
+		ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE;
+	rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+				 &packet_size_len);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	i += packet_size_len;
+	memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
+	i += ECRYPTFS_SIG_SIZE_HEX;
+	/* The encrypted key includes 1 byte cipher code and 2 byte checksum */
+	rc = write_packet_length(&message[i], crypt_stat->key_size + 3,
+				 &packet_size_len);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	i += packet_size_len;
+	message[i++] = cipher_code;
+	memcpy(&message[i], crypt_stat->key, crypt_stat->key_size);
+	i += crypt_stat->key_size;
+	for (j = 0; j < crypt_stat->key_size; j++)
+		checksum += crypt_stat->key[j];
+	message[i++] = (checksum / 256) % 256;
+	message[i++] = (checksum % 256);
+	*packet_len = i;
+out:
+	return rc;
+}
+
+static int
+parse_tag_67_packet(struct ecryptfs_key_record *key_rec,
+		    struct ecryptfs_message *msg)
+{
+	size_t i = 0;
+	char *data;
+	size_t data_len;
+	size_t message_len;
+	int rc;
+
+	/*
+	 *              ***** TAG 65 Packet Format *****
+	 *    | Content Type                       | 1 byte       |
+	 *    | Status Indicator                   | 1 byte       |
+	 *    | Encrypted File Encryption Key Size | 1 or 2 bytes |
+	 *    | Encrypted File Encryption Key      | arbitrary    |
+	 */
+	message_len = msg->data_len;
+	data = msg->data;
+	/* verify that everything through the encrypted FEK size is present */
+	if (message_len < 4) {
+		rc = -EIO;
+		goto out;
+	}
+	if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) {
+		ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_67\n");
+		rc = -EIO;
+		goto out;
+	}
+	if (data[i++]) {
+		ecryptfs_printk(KERN_ERR, "Status indicator has non zero value"
+				" [%d]\n", data[i-1]);
+		rc = -EIO;
+		goto out;
+	}
+	rc = parse_packet_length(&data[i], &key_rec->enc_key_size, &data_len);
+	if (rc) {
+		ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+				"rc = [%d]\n", rc);
+		goto out;
+	}
+	i += data_len;
+	if (message_len < (i + key_rec->enc_key_size)) {
+		ecryptfs_printk(KERN_ERR, "message_len [%d]; max len is [%d]\n",
+				message_len, (i + key_rec->enc_key_size));
+		rc = -EIO;
+		goto out;
+	}
+	if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
+		ecryptfs_printk(KERN_ERR, "Encrypted key_size [%d] larger than "
+				"the maximum key size [%d]\n",
+				key_rec->enc_key_size,
+				ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
+		rc = -EIO;
+		goto out;
+	}
+	memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size);
+out:
+	return rc;
+}
+
+/**
+ * decrypt_pki_encrypted_session_key - Decrypt the session key with
+ * the given auth_tok.
+ *
+ * Returns Zero on success; non-zero error otherwise.
+ */
+static int decrypt_pki_encrypted_session_key(
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+	struct ecryptfs_auth_tok *auth_tok,
+	struct ecryptfs_crypt_stat *crypt_stat)
+{
+	u16 cipher_code = 0;
+	struct ecryptfs_msg_ctx *msg_ctx;
+	struct ecryptfs_message *msg = NULL;
+	char *netlink_message;
+	size_t netlink_message_length;
+	int rc;
+
+	rc = write_tag_64_packet(mount_crypt_stat->global_auth_tok_sig,
+				 &(auth_tok->session_key),
+				 &netlink_message, &netlink_message_length);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet");
+		goto out;
+	}
+	rc = ecryptfs_send_message(ecryptfs_transport, netlink_message,
+				   netlink_message_length, &msg_ctx);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error sending netlink message\n");
+		goto out;
+	}
+	rc = ecryptfs_wait_for_response(msg_ctx, &msg);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failed to receive tag 65 packet "
+				"from the user space daemon\n");
+		rc = -EIO;
+		goto out;
+	}
+	rc = parse_tag_65_packet(&(auth_tok->session_key),
+				 &cipher_code, msg);
+	if (rc) {
+		printk(KERN_ERR "Failed to parse tag 65 packet; rc = [%d]\n",
+		       rc);
+		goto out;
+	}
+	auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
+	memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
+	       auth_tok->session_key.decrypted_key_size);
+	crypt_stat->key_size = auth_tok->session_key.decrypted_key_size;
+	rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n",
+				cipher_code)
+		goto out;
+	}
+	crypt_stat->flags |= ECRYPTFS_KEY_VALID;
+	if (ecryptfs_verbosity > 0) {
+		ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
+		ecryptfs_dump_hex(crypt_stat->key,
+				  crypt_stat->key_size);
+	}
+out:
+	if (msg)
+		kfree(msg);
+	return rc;
+}
+
+static void wipe_auth_tok_list(struct list_head *auth_tok_list_head)
+{
+	struct list_head *walker;
+	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
+
+	walker = auth_tok_list_head->next;
+	while (walker != auth_tok_list_head) {
+		auth_tok_list_item =
+		    list_entry(walker, struct ecryptfs_auth_tok_list_item,
+			       list);
+		walker = auth_tok_list_item->list.next;
+		memset(auth_tok_list_item, 0,
+		       sizeof(struct ecryptfs_auth_tok_list_item));
+		kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
+				auth_tok_list_item);
+	}
+	auth_tok_list_head->next = NULL;
+}
+
+struct kmem_cache *ecryptfs_auth_tok_list_item_cache;
+
+
+/**
+ * parse_tag_1_packet
+ * @crypt_stat: The cryptographic context to modify based on packet
+ *              contents.
+ * @data: The raw bytes of the packet.
+ * @auth_tok_list: eCryptfs parses packets into authentication tokens;
+ *                 a new authentication token will be placed at the end
+ *                 of this list for this packet.
+ * @new_auth_tok: Pointer to a pointer to memory that this function
+ *                allocates; sets the memory address of the pointer to
+ *                NULL on error. This object is added to the
+ *                auth_tok_list.
+ * @packet_size: This function writes the size of the parsed packet
+ *               into this memory location; zero on error.
+ *
+ * Returns zero on success; non-zero on error.
+ */
+static int
+parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
+		   unsigned char *data, struct list_head *auth_tok_list,
+		   struct ecryptfs_auth_tok **new_auth_tok,
+		   size_t *packet_size, size_t max_packet_size)
+{
+	size_t body_size;
+	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
+	size_t length_size;
+	int rc = 0;
+
+	(*packet_size) = 0;
+	(*new_auth_tok) = NULL;
+
+	/* we check that:
+	 *   one byte for the Tag 1 ID flag
+	 *   two bytes for the body size
+	 * do not exceed the maximum_packet_size
+	 */
+	if (unlikely((*packet_size) + 3 > max_packet_size)) {
+		ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	/* check for Tag 1 identifier - one byte */
+	if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) {
+		ecryptfs_printk(KERN_ERR, "Enter w/ first byte != 0x%.2x\n",
+				ECRYPTFS_TAG_1_PACKET_TYPE);
+		rc = -EINVAL;
+		goto out;
+	}
+	/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
+	 * at end of function upon failure */
+	auth_tok_list_item =
+		kmem_cache_alloc(ecryptfs_auth_tok_list_item_cache,
+				 GFP_KERNEL);
+	if (!auth_tok_list_item) {
+		ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(auth_tok_list_item, 0,
+	       sizeof(struct ecryptfs_auth_tok_list_item));
+	(*new_auth_tok) = &auth_tok_list_item->auth_tok;
+	/* check for body size - one to two bytes
+	 *
+	 *              ***** TAG 1 Packet Format *****
+	 *    | version number                     | 1 byte       |
+	 *    | key ID                             | 8 bytes      |
+	 *    | public key algorithm               | 1 byte       |
+	 *    | encrypted session key              | arbitrary    |
+	 */
+	rc = parse_packet_length(&data[(*packet_size)], &body_size,
+				 &length_size);
+	if (rc) {
+		ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
+				"rc = [%d]\n", rc);
+		goto out_free;
+	}
+	if (unlikely(body_size < (0x02 + ECRYPTFS_SIG_SIZE))) {
+		ecryptfs_printk(KERN_WARNING, "Invalid body size ([%d])\n",
+				body_size);
+		rc = -EINVAL;
+		goto out_free;
+	}
+	(*packet_size) += length_size;
+	if (unlikely((*packet_size) + body_size > max_packet_size)) {
+		ecryptfs_printk(KERN_ERR, "Packet size exceeds max\n");
+		rc = -EINVAL;
+		goto out_free;
+	}
+	/* Version 3 (from RFC2440) - one byte */
+	if (unlikely(data[(*packet_size)++] != 0x03)) {
+		ecryptfs_printk(KERN_DEBUG, "Unknown version number "
+				"[%d]\n", data[(*packet_size) - 1]);
+		rc = -EINVAL;
+		goto out_free;
+	}
+	/* Read Signature */
+	ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature,
+			&data[(*packet_size)], ECRYPTFS_SIG_SIZE);
+	*packet_size += ECRYPTFS_SIG_SIZE;
+	/* This byte is skipped because the kernel does not need to
+	 * know which public key encryption algorithm was used */
+	(*packet_size)++;
+	(*new_auth_tok)->session_key.encrypted_key_size =
+		body_size - (0x02 + ECRYPTFS_SIG_SIZE);
+	if ((*new_auth_tok)->session_key.encrypted_key_size
+	    > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
+		ecryptfs_printk(KERN_ERR, "Tag 1 packet contains key larger "
+				"than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES");
+		rc = -EINVAL;
+		goto out;
+	}
+	ecryptfs_printk(KERN_DEBUG, "Encrypted key size = [%d]\n",
+			(*new_auth_tok)->session_key.encrypted_key_size);
+	memcpy((*new_auth_tok)->session_key.encrypted_key,
+	       &data[(*packet_size)], (body_size - 0x02 - ECRYPTFS_SIG_SIZE));
+	(*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size;
+	(*new_auth_tok)->session_key.flags &=
+		~ECRYPTFS_CONTAINS_DECRYPTED_KEY;
+	(*new_auth_tok)->session_key.flags |=
+		ECRYPTFS_CONTAINS_ENCRYPTED_KEY;
+	(*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY;
+	(*new_auth_tok)->flags |= ECRYPTFS_PRIVATE_KEY;
+	/* TODO: Why are we setting this flag here? Don't we want the
+	 * userspace to decrypt the session key? */
+	(*new_auth_tok)->session_key.flags &=
+		~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
+	(*new_auth_tok)->session_key.flags &=
+		~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
+	list_add(&auth_tok_list_item->list, auth_tok_list);
+	goto out;
+out_free:
+	(*new_auth_tok) = NULL;
+	memset(auth_tok_list_item, 0,
+	       sizeof(struct ecryptfs_auth_tok_list_item));
+	kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
+			auth_tok_list_item);
+out:
+	if (rc)
+		(*packet_size) = 0;
+	return rc;
+}
+
 /**
  * parse_tag_3_packet
  * @crypt_stat: The cryptographic context to modify based on packet
@@ -178,10 +652,10 @@
 		   struct ecryptfs_auth_tok **new_auth_tok,
 		   size_t *packet_size, size_t max_packet_size)
 {
-	int rc = 0;
 	size_t body_size;
 	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
 	size_t length_size;
+	int rc = 0;
 
 	(*packet_size) = 0;
 	(*new_auth_tok) = NULL;
@@ -319,10 +793,10 @@
 	(*new_auth_tok)->token_type = ECRYPTFS_PASSWORD;
 	/* TODO: Parametarize; we might actually want userspace to
 	 * decrypt the session key. */
-	ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
-			    ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
-	ECRYPTFS_CLEAR_FLAG((*new_auth_tok)->session_key.flags,
-			    ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
+	(*new_auth_tok)->session_key.flags &=
+			    ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
+	(*new_auth_tok)->session_key.flags &=
+			    ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
 	list_add(&auth_tok_list_item->list, auth_tok_list);
 	goto out;
 out_free:
@@ -358,9 +832,9 @@
 		    size_t max_contents_bytes, size_t *tag_11_contents_size,
 		    size_t *packet_size, size_t max_packet_size)
 {
-	int rc = 0;
 	size_t body_size;
 	size_t length_size;
+	int rc = 0;
 
 	(*packet_size) = 0;
 	(*tag_11_contents_size) = 0;
@@ -459,7 +933,6 @@
 	struct ecryptfs_password *password_s_ptr;
 	struct scatterlist src_sg[2], dst_sg[2];
 	struct mutex *tfm_mutex = NULL;
-	/* TODO: Use virt_to_scatterlist for these */
 	char *encrypted_session_key;
 	char *session_key;
 	struct blkcipher_desc desc = {
@@ -468,8 +941,7 @@
 	int rc = 0;
 
 	password_s_ptr = &auth_tok->token.password;
-	if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags,
-				ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET))
+	if (password_s_ptr->flags & ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)
 		ecryptfs_printk(KERN_DEBUG, "Session key encryption key "
 				"set; skipping key generation\n");
 	ecryptfs_printk(KERN_DEBUG, "Session key encryption key (size [%d])"
@@ -551,7 +1023,7 @@
 	auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
 	memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
 	       auth_tok->session_key.decrypted_key_size);
-	ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
+	crypt_stat->flags |= ECRYPTFS_KEY_VALID;
 	ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
 	if (ecryptfs_verbosity > 0)
 		ecryptfs_dump_hex(crypt_stat->key,
@@ -587,7 +1059,6 @@
 			      struct dentry *ecryptfs_dentry)
 {
 	size_t i = 0;
-	int rc = 0;
 	size_t found_auth_tok = 0;
 	size_t next_packet_is_auth_tok_packet;
 	char sig[ECRYPTFS_SIG_SIZE_HEX];
@@ -603,6 +1074,7 @@
 	unsigned char sig_tmp_space[ECRYPTFS_SIG_SIZE];
 	size_t tag_11_contents_size;
 	size_t tag_11_packet_size;
+	int rc = 0;
 
 	INIT_LIST_HEAD(&auth_tok_list);
 	/* Parse the header to find as many packets as we can, these will be
@@ -654,8 +1126,21 @@
 					sig_tmp_space, tag_11_contents_size);
 			new_auth_tok->token.password.signature[
 				ECRYPTFS_PASSWORD_SIG_SIZE] = '\0';
-			ECRYPTFS_SET_FLAG(crypt_stat->flags,
-					  ECRYPTFS_ENCRYPTED);
+			crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
+			break;
+		case ECRYPTFS_TAG_1_PACKET_TYPE:
+			rc = parse_tag_1_packet(crypt_stat,
+						(unsigned char *)&src[i],
+						&auth_tok_list, &new_auth_tok,
+						&packet_size, max_packet_size);
+			if (rc) {
+				ecryptfs_printk(KERN_ERR, "Error parsing "
+						"tag 1 packet\n");
+				rc = -EIO;
+				goto out_wipe_list;
+			}
+			i += packet_size;
+			crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
 			break;
 		case ECRYPTFS_TAG_11_PACKET_TYPE:
 			ecryptfs_printk(KERN_WARNING, "Invalid packet set "
@@ -704,31 +1189,46 @@
 			goto leave_list;
 			/* TODO: Transfer the common salt into the
 			 * crypt_stat salt */
+		} else if ((candidate_auth_tok->token_type
+			    == ECRYPTFS_PRIVATE_KEY)
+			   && !strncmp(candidate_auth_tok->token.private_key.signature,
+				     sig, ECRYPTFS_SIG_SIZE_HEX)) {
+			found_auth_tok = 1;
+			goto leave_list;
 		}
 	}
-leave_list:
 	if (!found_auth_tok) {
 		ecryptfs_printk(KERN_ERR, "Could not find authentication "
 				"token on temporary list for sig [%.*s]\n",
 				ECRYPTFS_SIG_SIZE_HEX, sig);
 		rc = -EIO;
 		goto out_wipe_list;
-	} else {
+	}
+leave_list:
+	rc = -ENOTSUPP;
+	if (candidate_auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
+		memcpy(&(candidate_auth_tok->token.private_key),
+		       &(chosen_auth_tok->token.private_key),
+		       sizeof(struct ecryptfs_private_key));
+		rc = decrypt_pki_encrypted_session_key(mount_crypt_stat,
+						       candidate_auth_tok,
+						       crypt_stat);
+	} else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) {
 		memcpy(&(candidate_auth_tok->token.password),
 		       &(chosen_auth_tok->token.password),
 		       sizeof(struct ecryptfs_password));
 		rc = decrypt_session_key(candidate_auth_tok, crypt_stat);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "Error decrypting the "
-					"session key\n");
-			goto out_wipe_list;
-		}
-		rc = ecryptfs_compute_root_iv(crypt_stat);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "Error computing "
-					"the root IV\n");
-			goto out_wipe_list;
-		}
+	}
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error decrypting the "
+				"session key; rc = [%d]\n", rc);
+		goto out_wipe_list;
+	}
+	rc = ecryptfs_compute_root_iv(crypt_stat);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error computing "
+				"the root IV\n");
+		goto out_wipe_list;
 	}
 	rc = ecryptfs_init_crypt_ctx(crypt_stat);
 	if (rc) {
@@ -741,6 +1241,145 @@
 out:
 	return rc;
 }
+static int
+pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,
+			struct ecryptfs_crypt_stat *crypt_stat,
+			struct ecryptfs_key_record *key_rec)
+{
+	struct ecryptfs_msg_ctx *msg_ctx = NULL;
+	char *netlink_payload;
+	size_t netlink_payload_length;
+	struct ecryptfs_message *msg;
+	int rc;
+
+	rc = write_tag_66_packet(auth_tok->token.private_key.signature,
+				 ecryptfs_code_for_cipher_string(crypt_stat),
+				 crypt_stat, &netlink_payload,
+				 &netlink_payload_length);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n");
+		goto out;
+	}
+	rc = ecryptfs_send_message(ecryptfs_transport, netlink_payload,
+				   netlink_payload_length, &msg_ctx);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error sending netlink message\n");
+		goto out;
+	}
+	rc = ecryptfs_wait_for_response(msg_ctx, &msg);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failed to receive tag 67 packet "
+				"from the user space daemon\n");
+		rc = -EIO;
+		goto out;
+	}
+	rc = parse_tag_67_packet(key_rec, msg);
+	if (rc)
+		ecryptfs_printk(KERN_ERR, "Error parsing tag 67 packet\n");
+	kfree(msg);
+out:
+	if (netlink_payload)
+		kfree(netlink_payload);
+	return rc;
+}
+/**
+ * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet
+ * @dest: Buffer into which to write the packet
+ * @max: Maximum number of bytes that can be writtn
+ * @packet_size: This function will write the number of bytes that end
+ *               up constituting the packet; set to zero on error
+ *
+ * Returns zero on success; non-zero on error.
+ */
+static int
+write_tag_1_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok,
+		   struct ecryptfs_crypt_stat *crypt_stat,
+		   struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
+		   struct ecryptfs_key_record *key_rec, size_t *packet_size)
+{
+	size_t i;
+	size_t encrypted_session_key_valid = 0;
+	size_t key_rec_size;
+	size_t packet_size_length;
+	int rc = 0;
+
+	(*packet_size) = 0;
+	ecryptfs_from_hex(key_rec->sig, auth_tok->token.private_key.signature,
+			  ECRYPTFS_SIG_SIZE);
+	encrypted_session_key_valid = 0;
+	for (i = 0; i < crypt_stat->key_size; i++)
+		encrypted_session_key_valid |=
+			auth_tok->session_key.encrypted_key[i];
+	if (encrypted_session_key_valid) {
+		memcpy(key_rec->enc_key,
+		       auth_tok->session_key.encrypted_key,
+		       auth_tok->session_key.encrypted_key_size);
+		goto encrypted_session_key_set;
+	}
+	if (auth_tok->session_key.encrypted_key_size == 0)
+		auth_tok->session_key.encrypted_key_size =
+			auth_tok->token.private_key.key_size;
+	rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failed to encrypt session key "
+				"via a pki");
+		goto out;
+	}
+	if (ecryptfs_verbosity > 0) {
+		ecryptfs_printk(KERN_DEBUG, "Encrypted key:\n");
+		ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size);
+	}
+encrypted_session_key_set:
+	/* Now we have a valid key_rec.  Append it to the
+	 * key_rec set. */
+	key_rec_size = (sizeof(struct ecryptfs_key_record)
+			- ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES
+			+ (key_rec->enc_key_size));
+	/* TODO: Include a packet size limit as a parameter to this
+	 * function once we have multi-packet headers (for versions
+	 * later than 0.1 */
+	if (key_rec_size >= ECRYPTFS_MAX_KEYSET_SIZE) {
+		ecryptfs_printk(KERN_ERR, "Keyset too large\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	/*              ***** TAG 1 Packet Format *****
+	 *    | version number                     | 1 byte       |
+	 *    | key ID                             | 8 bytes      |
+	 *    | public key algorithm               | 1 byte       |
+	 *    | encrypted session key              | arbitrary    |
+	 */
+	if ((0x02 + ECRYPTFS_SIG_SIZE + key_rec->enc_key_size) >= max) {
+		ecryptfs_printk(KERN_ERR,
+				"Authentication token is too large\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE;
+	/* This format is inspired by OpenPGP; see RFC 2440
+	 * packet tag 1 */
+	rc = write_packet_length(&dest[(*packet_size)],
+				 (0x02 + ECRYPTFS_SIG_SIZE +
+				 key_rec->enc_key_size),
+				 &packet_size_length);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet "
+				"header; cannot generate packet length\n");
+		goto out;
+	}
+	(*packet_size) += packet_size_length;
+	dest[(*packet_size)++] = 0x03; /* version 3 */
+	memcpy(&dest[(*packet_size)], key_rec->sig, ECRYPTFS_SIG_SIZE);
+	(*packet_size) += ECRYPTFS_SIG_SIZE;
+	dest[(*packet_size)++] = RFC2440_CIPHER_RSA;
+	memcpy(&dest[(*packet_size)], key_rec->enc_key,
+	       key_rec->enc_key_size);
+	(*packet_size) += key_rec->enc_key_size;
+out:
+	if (rc)
+		(*packet_size) = 0;
+	return rc;
+}
 
 /**
  * write_tag_11_packet
@@ -756,8 +1395,8 @@
 write_tag_11_packet(char *dest, int max, char *contents, size_t contents_length,
 		    size_t *packet_length)
 {
-	int rc = 0;
 	size_t packet_size_length;
+	int rc = 0;
 
 	(*packet_length) = 0;
 	if ((13 + contents_length) > max) {
@@ -815,7 +1454,6 @@
 		   struct ecryptfs_key_record *key_rec, size_t *packet_size)
 {
 	size_t i;
-	size_t signature_is_valid = 0;
 	size_t encrypted_session_key_valid = 0;
 	char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
 	struct scatterlist dest_sg[2];
@@ -831,19 +1469,14 @@
 	int rc = 0;
 
 	(*packet_size) = 0;
-	/* Check for a valid signature on the auth_tok */
-	for (i = 0; i < ECRYPTFS_SIG_SIZE_HEX; i++)
-		signature_is_valid |= auth_tok->token.password.signature[i];
-	if (!signature_is_valid)
-		BUG();
-	ecryptfs_from_hex((*key_rec).sig, auth_tok->token.password.signature,
+	ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature,
 			  ECRYPTFS_SIG_SIZE);
 	encrypted_session_key_valid = 0;
 	for (i = 0; i < crypt_stat->key_size; i++)
 		encrypted_session_key_valid |=
 			auth_tok->session_key.encrypted_key[i];
 	if (encrypted_session_key_valid) {
-		memcpy((*key_rec).enc_key,
+		memcpy(key_rec->enc_key,
 		       auth_tok->session_key.encrypted_key,
 		       auth_tok->session_key.encrypted_key_size);
 		goto encrypted_session_key_set;
@@ -856,10 +1489,10 @@
 		memset((crypt_stat->key + 24), 0, 8);
 		auth_tok->session_key.encrypted_key_size = 32;
 	}
-	(*key_rec).enc_key_size =
+	key_rec->enc_key_size =
 		auth_tok->session_key.encrypted_key_size;
-	if (ECRYPTFS_CHECK_FLAG(auth_tok->token.password.flags,
-				ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET)) {
+	if (auth_tok->token.password.flags &
+	    ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) {
 		ecryptfs_printk(KERN_DEBUG, "Using previously generated "
 				"session key encryption key of size [%d]\n",
 				auth_tok->token.password.
@@ -877,15 +1510,15 @@
 		ecryptfs_dump_hex(session_key_encryption_key, 16);
 	}
 	rc = virt_to_scatterlist(crypt_stat->key,
-				 (*key_rec).enc_key_size, src_sg, 2);
+				 key_rec->enc_key_size, src_sg, 2);
 	if (!rc) {
 		ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
 				"for crypt_stat session key\n");
 		rc = -ENOMEM;
 		goto out;
 	}
-	rc = virt_to_scatterlist((*key_rec).enc_key,
-				 (*key_rec).enc_key_size, dest_sg, 2);
+	rc = virt_to_scatterlist(key_rec->enc_key,
+				 key_rec->enc_key_size, dest_sg, 2);
 	if (!rc) {
 		ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
 				"for crypt_stat encrypted session key\n");
@@ -941,14 +1574,14 @@
 		mutex_unlock(tfm_mutex);
 	ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n");
 	if (ecryptfs_verbosity > 0)
-		ecryptfs_dump_hex((*key_rec).enc_key,
-				  (*key_rec).enc_key_size);
+		ecryptfs_dump_hex(key_rec->enc_key,
+				  key_rec->enc_key_size);
 encrypted_session_key_set:
 	/* Now we have a valid key_rec.  Append it to the
 	 * key_rec set. */
 	key_rec_size = (sizeof(struct ecryptfs_key_record)
 			- ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES
-			+ ((*key_rec).enc_key_size));
+			+ (key_rec->enc_key_size));
 	/* TODO: Include a packet size limit as a parameter to this
 	 * function once we have multi-packet headers (for versions
 	 * later than 0.1 */
@@ -960,7 +1593,7 @@
 	/* TODO: Packet size limit */
 	/* We have 5 bytes of surrounding packet data */
 	if ((0x05 + ECRYPTFS_SALT_SIZE
-	     + (*key_rec).enc_key_size) >= max) {
+	     + key_rec->enc_key_size) >= max) {
 		ecryptfs_printk(KERN_ERR, "Authentication token is too "
 				"large\n");
 		rc = -EINVAL;
@@ -972,7 +1605,7 @@
 	/* ver+cipher+s2k+hash+salt+iter+enc_key */
 	rc = write_packet_length(&dest[(*packet_size)],
 				 (0x05 + ECRYPTFS_SALT_SIZE
-				  + (*key_rec).enc_key_size),
+				  + key_rec->enc_key_size),
 				 &packet_size_length);
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error generating tag 3 packet "
@@ -995,9 +1628,9 @@
 	       ECRYPTFS_SALT_SIZE);
 	(*packet_size) += ECRYPTFS_SALT_SIZE;	/* salt */
 	dest[(*packet_size)++] = 0x60;	/* hash iterations (65536) */
-	memcpy(&dest[(*packet_size)], (*key_rec).enc_key,
-	       (*key_rec).enc_key_size);
-	(*packet_size) += (*key_rec).enc_key_size;
+	memcpy(&dest[(*packet_size)], key_rec->enc_key,
+	       key_rec->enc_key_size);
+	(*packet_size) += key_rec->enc_key_size;
 out:
 	if (desc.tfm && !tfm_mutex)
 		crypto_free_blkcipher(desc.tfm);
@@ -1027,13 +1660,13 @@
 				 struct dentry *ecryptfs_dentry, size_t *len,
 				 size_t max)
 {
-	int rc = 0;
 	struct ecryptfs_auth_tok *auth_tok;
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
 		&ecryptfs_superblock_to_private(
 			ecryptfs_dentry->d_sb)->mount_crypt_stat;
 	size_t written;
 	struct ecryptfs_key_record key_rec;
+	int rc = 0;
 
 	(*len) = 0;
 	if (mount_crypt_stat->global_auth_tok) {
@@ -1060,20 +1693,23 @@
 				goto out;
 			}
 			(*len) += written;
+		} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
+			rc = write_tag_1_packet(dest_base + (*len),
+						max, auth_tok,
+						crypt_stat,mount_crypt_stat,
+						&key_rec, &written);
+			if (rc) {
+				ecryptfs_printk(KERN_WARNING, "Error "
+						"writing tag 1 packet\n");
+				goto out;
+			}
+			(*len) += written;
 		} else {
 			ecryptfs_printk(KERN_WARNING, "Unsupported "
 					"authentication token type\n");
 			rc = -EINVAL;
 			goto out;
 		}
-		if (rc) {
-			ecryptfs_printk(KERN_WARNING, "Error writing "
-					"authentication token packet with sig "
-					"= [%s]\n",
-					mount_crypt_stat->global_auth_tok_sig);
-			rc = -EIO;
-			goto out;
-		}
 	} else
 		BUG();
 	if (likely((max - (*len)) > 0)) {
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index fe41ab1..26fe405 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -3,9 +3,10 @@
  *
  * Copyright (C) 1997-2003 Erez Zadok
  * Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *              Michael C. Thompson <mcthomps@us.ibm.com>
+ *              Tyler Hicks <tyhicks@ou.edu>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -48,6 +49,43 @@
 		 "Initial verbosity level (0 or 1; defaults to "
 		 "0, which is Quiet)");
 
+/**
+ * Module parameter that defines the number of netlink message buffer
+ * elements
+ */
+unsigned int ecryptfs_message_buf_len = ECRYPTFS_DEFAULT_MSG_CTX_ELEMS;
+
+module_param(ecryptfs_message_buf_len, uint, 0);
+MODULE_PARM_DESC(ecryptfs_message_buf_len,
+		 "Number of message buffer elements");
+
+/**
+ * Module parameter that defines the maximum guaranteed amount of time to wait
+ * for a response through netlink.  The actual sleep time will be, more than
+ * likely, a small amount greater than this specified value, but only less if
+ * the netlink message successfully arrives.
+ */
+signed long ecryptfs_message_wait_timeout = ECRYPTFS_MAX_MSG_CTX_TTL / HZ;
+
+module_param(ecryptfs_message_wait_timeout, long, 0);
+MODULE_PARM_DESC(ecryptfs_message_wait_timeout,
+		 "Maximum number of seconds that an operation will "
+		 "sleep while waiting for a message response from "
+		 "userspace");
+
+/**
+ * Module parameter that is an estimate of the maximum number of users
+ * that will be concurrently using eCryptfs. Set this to the right
+ * value to balance performance and memory use.
+ */
+unsigned int ecryptfs_number_of_users = ECRYPTFS_DEFAULT_NUM_USERS;
+
+module_param(ecryptfs_number_of_users, uint, 0);
+MODULE_PARM_DESC(ecryptfs_number_of_users, "An estimate of the number of "
+		 "concurrent users of eCryptfs");
+
+unsigned int ecryptfs_transport = ECRYPTFS_DEFAULT_TRANSPORT;
+
 void __ecryptfs_printk(const char *fmt, ...)
 {
 	va_list args;
@@ -124,7 +162,8 @@
 enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug,
        ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher,
        ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes,
-       ecryptfs_opt_passthrough, ecryptfs_opt_err };
+       ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
+       ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
 
 static match_table_t tokens = {
 	{ecryptfs_opt_sig, "sig=%s"},
@@ -135,6 +174,8 @@
 	{ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"},
 	{ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"},
 	{ecryptfs_opt_passthrough, "ecryptfs_passthrough"},
+	{ecryptfs_opt_xattr_metadata, "ecryptfs_xattr_metadata"},
+	{ecryptfs_opt_encrypted_view, "ecryptfs_encrypted_view"},
 	{ecryptfs_opt_err, NULL}
 };
 
@@ -275,6 +316,16 @@
 			mount_crypt_stat->flags |=
 				ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED;
 			break;
+		case ecryptfs_opt_xattr_metadata:
+			mount_crypt_stat->flags |=
+				ECRYPTFS_XATTR_METADATA_ENABLED;
+			break;
+		case ecryptfs_opt_encrypted_view:
+			mount_crypt_stat->flags |=
+				ECRYPTFS_XATTR_METADATA_ENABLED;
+			mount_crypt_stat->flags |=
+				ECRYPTFS_ENCRYPTED_VIEW_ENABLED;
+			break;
 		case ecryptfs_opt_err:
 		default:
 			ecryptfs_printk(KERN_WARNING,
@@ -347,9 +398,10 @@
 		rc = -EINVAL;
 		goto out;
 	}
-	if (auth_tok->token_type != ECRYPTFS_PASSWORD) {
+	if (auth_tok->token_type != ECRYPTFS_PASSWORD
+	    && auth_tok->token_type != ECRYPTFS_PRIVATE_KEY) {
 		ecryptfs_printk(KERN_ERR, "Invalid auth_tok structure "
-				"returned from key\n");
+				"returned from key query\n");
 		rc = -EINVAL;
 		goto out;
 	}
@@ -590,6 +642,11 @@
 		.size = PAGE_CACHE_SIZE,
 	},
 	{
+		.cache = &ecryptfs_xattr_cache,
+		.name = "ecryptfs_xattr_cache",
+		.size = PAGE_CACHE_SIZE,
+	},
+	{
 		.cache = &ecryptfs_lower_page_cache,
 		.name = "ecryptfs_lower_page_cache",
 		.size = PAGE_CACHE_SIZE,
@@ -695,7 +752,8 @@
 	{ECRYPTFS_VERSIONING_PASSPHRASE, "passphrase"},
 	{ECRYPTFS_VERSIONING_PUBKEY, "pubkey"},
 	{ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"},
-	{ECRYPTFS_VERSIONING_POLICY, "policy"}
+	{ECRYPTFS_VERSIONING_POLICY, "policy"},
+	{ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"}
 };
 
 static ssize_t version_str_show(struct ecryptfs_obj *obj, char *buff)
@@ -794,6 +852,11 @@
 		ecryptfs_free_kmem_caches();
 		goto out;
 	}
+	rc = ecryptfs_init_messaging(ecryptfs_transport);
+	if (rc) {
+		ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
+				"initialize the eCryptfs netlink socket\n");
+	}
 out:
 	return rc;
 }
@@ -805,6 +868,7 @@
 	sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
 			  &sysfs_attr_version_str.attr);
 	subsystem_unregister(&ecryptfs_subsys);
+	ecryptfs_release_messaging(ecryptfs_transport);
 	unregister_filesystem(&ecryptfs_fs_type);
 	ecryptfs_free_kmem_caches();
 }
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c
new file mode 100644
index 0000000..47d7e7b
--- /dev/null
+++ b/fs/ecryptfs/messaging.c
@@ -0,0 +1,515 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2004-2006 International Business Machines Corp.
+ *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
+ *		Tyler Hicks <tyhicks@ou.edu>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include "ecryptfs_kernel.h"
+
+static LIST_HEAD(ecryptfs_msg_ctx_free_list);
+static LIST_HEAD(ecryptfs_msg_ctx_alloc_list);
+static struct mutex ecryptfs_msg_ctx_lists_mux;
+
+static struct hlist_head *ecryptfs_daemon_id_hash;
+static struct mutex ecryptfs_daemon_id_hash_mux;
+static int ecryptfs_hash_buckets;
+#define ecryptfs_uid_hash(uid) \
+        hash_long((unsigned long)uid, ecryptfs_hash_buckets)
+
+static unsigned int ecryptfs_msg_counter;
+static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr;
+
+/**
+ * ecryptfs_acquire_free_msg_ctx
+ * @msg_ctx: The context that was acquired from the free list
+ *
+ * Acquires a context element from the free list and locks the mutex
+ * on the context.  Returns zero on success; non-zero on error or upon
+ * failure to acquire a free context element.  Be sure to lock the
+ * list mutex before calling.
+ */
+static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx)
+{
+	struct list_head *p;
+	int rc;
+
+	if (list_empty(&ecryptfs_msg_ctx_free_list)) {
+		ecryptfs_printk(KERN_WARNING, "The eCryptfs free "
+				"context list is empty.  It may be helpful to "
+				"specify the ecryptfs_message_buf_len "
+				"parameter to be greater than the current "
+				"value of [%d]\n", ecryptfs_message_buf_len);
+		rc = -ENOMEM;
+		goto out;
+	}
+	list_for_each(p, &ecryptfs_msg_ctx_free_list) {
+		*msg_ctx = list_entry(p, struct ecryptfs_msg_ctx, node);
+		if (mutex_trylock(&(*msg_ctx)->mux)) {
+			(*msg_ctx)->task = current;
+			rc = 0;
+			goto out;
+		}
+	}
+	rc = -ENOMEM;
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_msg_ctx_free_to_alloc
+ * @msg_ctx: The context to move from the free list to the alloc list
+ *
+ * Be sure to lock the list mutex and the context mutex before
+ * calling.
+ */
+static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)
+{
+	list_move(&msg_ctx->node, &ecryptfs_msg_ctx_alloc_list);
+	msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_PENDING;
+	msg_ctx->counter = ++ecryptfs_msg_counter;
+}
+
+/**
+ * ecryptfs_msg_ctx_alloc_to_free
+ * @msg_ctx: The context to move from the alloc list to the free list
+ *
+ * Be sure to lock the list mutex and the context mutex before
+ * calling.
+ */
+static void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)
+{
+	list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list);
+	if (msg_ctx->msg)
+		kfree(msg_ctx->msg);
+	msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE;
+}
+
+/**
+ * ecryptfs_find_daemon_id
+ * @uid: The user id which maps to the desired daemon id
+ * @id: If return value is zero, points to the desired daemon id
+ *      pointer
+ *
+ * Search the hash list for the given user id.  Returns zero if the
+ * user id exists in the list; non-zero otherwise.  The daemon id hash
+ * mutex should be held before calling this function.
+ */
+static int ecryptfs_find_daemon_id(uid_t uid, struct ecryptfs_daemon_id **id)
+{
+	struct hlist_node *elem;
+	int rc;
+
+	hlist_for_each_entry(*id, elem,
+			     &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)],
+			     id_chain) {
+		if ((*id)->uid == uid) {
+			rc = 0;
+			goto out;
+		}
+	}
+	rc = -EINVAL;
+out:
+	return rc;
+}
+
+static int ecryptfs_send_raw_message(unsigned int transport, u16 msg_type,
+				     pid_t pid)
+{
+	int rc;
+
+	switch(transport) {
+	case ECRYPTFS_TRANSPORT_NETLINK:
+		rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0, pid);
+		break;
+	case ECRYPTFS_TRANSPORT_CONNECTOR:
+	case ECRYPTFS_TRANSPORT_RELAYFS:
+	default:
+		rc = -ENOSYS;
+	}
+	return rc;
+}
+
+/**
+ * ecryptfs_process_helo
+ * @transport: The underlying transport (netlink, etc.)
+ * @uid: The user ID owner of the message
+ * @pid: The process ID for the userspace program that sent the
+ *       message
+ *
+ * Adds the uid and pid values to the daemon id hash.  If a uid
+ * already has a daemon pid registered, the daemon will be
+ * unregistered before the new daemon id is put into the hash list.
+ * Returns zero after adding a new daemon id to the hash list;
+ * non-zero otherwise.
+ */
+int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid)
+{
+	struct ecryptfs_daemon_id *new_id;
+	struct ecryptfs_daemon_id *old_id;
+	int rc;
+
+	mutex_lock(&ecryptfs_daemon_id_hash_mux);
+	new_id = kmalloc(sizeof(*new_id), GFP_KERNEL);
+	if (!new_id) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable "
+				"to register daemon [%d] for user\n", pid, uid);
+		goto unlock;
+	}
+	if (!ecryptfs_find_daemon_id(uid, &old_id)) {
+		printk(KERN_WARNING "Received request from user [%d] "
+		       "to register daemon [%d]; unregistering daemon "
+		       "[%d]\n", uid, pid, old_id->pid);
+		hlist_del(&old_id->id_chain);
+		rc = ecryptfs_send_raw_message(transport, ECRYPTFS_NLMSG_QUIT,
+					       old_id->pid);
+		if (rc)
+			printk(KERN_WARNING "Failed to send QUIT "
+			       "message to daemon [%d]; rc = [%d]\n",
+			       old_id->pid, rc);
+		kfree(old_id);
+	}
+	new_id->uid = uid;
+	new_id->pid = pid;
+	hlist_add_head(&new_id->id_chain,
+		       &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)]);
+	rc = 0;
+unlock:
+	mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+	return rc;
+}
+
+/**
+ * ecryptfs_process_quit
+ * @uid: The user ID owner of the message
+ * @pid: The process ID for the userspace program that sent the
+ *       message
+ *
+ * Deletes the corresponding daemon id for the given uid and pid, if
+ * it is the registered that is requesting the deletion. Returns zero
+ * after deleting the desired daemon id; non-zero otherwise.
+ */
+int ecryptfs_process_quit(uid_t uid, pid_t pid)
+{
+	struct ecryptfs_daemon_id *id;
+	int rc;
+
+	mutex_lock(&ecryptfs_daemon_id_hash_mux);
+	if (ecryptfs_find_daemon_id(uid, &id)) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_ERR, "Received request from user [%d] to "
+				"unregister unrecognized daemon [%d]\n", uid,
+				pid);
+		goto unlock;
+	}
+	if (id->pid != pid) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_WARNING, "Received request from user [%d] "
+				"with pid [%d] to unregister daemon [%d]\n",
+				uid, pid, id->pid);
+		goto unlock;
+	}
+	hlist_del(&id->id_chain);
+	kfree(id);
+	rc = 0;
+unlock:
+	mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+	return rc;
+}
+
+/**
+ * ecryptfs_process_reponse
+ * @msg: The ecryptfs message received; the caller should sanity check
+ *       msg->data_len
+ * @pid: The process ID of the userspace application that sent the
+ *       message
+ * @seq: The sequence number of the message
+ *
+ * Processes a response message after sending a operation request to
+ * userspace. Returns zero upon delivery to desired context element;
+ * non-zero upon delivery failure or error.
+ */
+int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
+			      pid_t pid, u32 seq)
+{
+	struct ecryptfs_daemon_id *id;
+	struct ecryptfs_msg_ctx *msg_ctx;
+	int msg_size;
+	int rc;
+
+	if (msg->index >= ecryptfs_message_buf_len) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_ERR, "Attempt to reference "
+				"context buffer at index [%d]; maximum "
+				"allowable is [%d]\n", msg->index,
+				(ecryptfs_message_buf_len - 1));
+		goto out;
+	}
+	msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];
+	mutex_lock(&msg_ctx->mux);
+	if (ecryptfs_find_daemon_id(msg_ctx->task->euid, &id)) {
+		rc = -EBADMSG;
+		ecryptfs_printk(KERN_WARNING, "User [%d] received a "
+				"message response from process [%d] but does "
+				"not have a registered daemon\n",
+				msg_ctx->task->euid, pid);
+		goto wake_up;
+	}
+	if (msg_ctx->task->euid != uid) {
+		rc = -EBADMSG;
+		ecryptfs_printk(KERN_WARNING, "Received message from user "
+				"[%d]; expected message from user [%d]\n",
+				uid, msg_ctx->task->euid);
+		goto unlock;
+	}
+	if (id->pid != pid) {
+		rc = -EBADMSG;
+		ecryptfs_printk(KERN_ERR, "User [%d] received a "
+				"message response from an unrecognized "
+				"process [%d]\n", msg_ctx->task->euid, pid);
+		goto unlock;
+	}
+	if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_WARNING, "Desired context element is not "
+				"pending a response\n");
+		goto unlock;
+	} else if (msg_ctx->counter != seq) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_WARNING, "Invalid message sequence; "
+				"expected [%d]; received [%d]\n",
+				msg_ctx->counter, seq);
+		goto unlock;
+	}
+	msg_size = sizeof(*msg) + msg->data_len;
+	msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL);
+	if (!msg_ctx->msg) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+		goto unlock;
+	}
+	memcpy(msg_ctx->msg, msg, msg_size);
+	msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE;
+	rc = 0;
+wake_up:
+	wake_up_process(msg_ctx->task);
+unlock:
+	mutex_unlock(&msg_ctx->mux);
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_send_message
+ * @transport: The transport over which to send the message (i.e.,
+ *             netlink)
+ * @data: The data to send
+ * @data_len: The length of data
+ * @msg_ctx: The message context allocated for the send
+ */
+int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+			  struct ecryptfs_msg_ctx **msg_ctx)
+{
+	struct ecryptfs_daemon_id *id;
+	int rc;
+
+	mutex_lock(&ecryptfs_daemon_id_hash_mux);
+	if (ecryptfs_find_daemon_id(current->euid, &id)) {
+		mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+		rc = -ENOTCONN;
+		ecryptfs_printk(KERN_ERR, "User [%d] does not have a daemon "
+				"registered\n", current->euid);
+		goto out;
+	}
+	mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+	mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+	rc = ecryptfs_acquire_free_msg_ctx(msg_ctx);
+	if (rc) {
+		mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+		ecryptfs_printk(KERN_WARNING, "Could not claim a free "
+				"context element\n");
+		goto out;
+	}
+	ecryptfs_msg_ctx_free_to_alloc(*msg_ctx);
+	mutex_unlock(&(*msg_ctx)->mux);
+	mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+	switch (transport) {
+	case ECRYPTFS_TRANSPORT_NETLINK:
+		rc = ecryptfs_send_netlink(data, data_len, *msg_ctx,
+					   ECRYPTFS_NLMSG_REQUEST, 0, id->pid);
+		break;
+	case ECRYPTFS_TRANSPORT_CONNECTOR:
+	case ECRYPTFS_TRANSPORT_RELAYFS:
+	default:
+		rc = -ENOSYS;
+	}
+	if (rc) {
+		printk(KERN_ERR "Error attempting to send message to userspace "
+		       "daemon; rc = [%d]\n", rc);
+	}
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_wait_for_response
+ * @msg_ctx: The context that was assigned when sending a message
+ * @msg: The incoming message from userspace; not set if rc != 0
+ *
+ * Sleeps until awaken by ecryptfs_receive_message or until the amount
+ * of time exceeds ecryptfs_message_wait_timeout.  If zero is
+ * returned, msg will point to a valid message from userspace; a
+ * non-zero value is returned upon failure to receive a message or an
+ * error occurs.
+ */
+int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
+			       struct ecryptfs_message **msg)
+{
+	signed long timeout = ecryptfs_message_wait_timeout * HZ;
+	int rc = 0;
+
+sleep:
+	timeout = schedule_timeout_interruptible(timeout);
+	mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+	mutex_lock(&msg_ctx->mux);
+	if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_DONE) {
+		if (timeout) {
+			mutex_unlock(&msg_ctx->mux);
+			mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+			goto sleep;
+		}
+		rc = -ENOMSG;
+	} else {
+		*msg = msg_ctx->msg;
+		msg_ctx->msg = NULL;
+	}
+	ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
+	mutex_unlock(&msg_ctx->mux);
+	mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+	return rc;
+}
+
+int ecryptfs_init_messaging(unsigned int transport)
+{
+	int i;
+	int rc = 0;
+
+	if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) {
+		ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS;
+		ecryptfs_printk(KERN_WARNING, "Specified number of users is "
+				"too large, defaulting to [%d] users\n",
+				ecryptfs_number_of_users);
+	}
+	mutex_init(&ecryptfs_daemon_id_hash_mux);
+	mutex_lock(&ecryptfs_daemon_id_hash_mux);
+	ecryptfs_hash_buckets = 0;
+	while (ecryptfs_number_of_users >> ++ecryptfs_hash_buckets);
+	ecryptfs_daemon_id_hash = kmalloc(sizeof(struct hlist_head)
+					  * ecryptfs_hash_buckets, GFP_KERNEL);
+	if (!ecryptfs_daemon_id_hash) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+		goto out;
+	}
+	for (i = 0; i < ecryptfs_hash_buckets; i++)
+		INIT_HLIST_HEAD(&ecryptfs_daemon_id_hash[i]);
+	mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+
+	ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx)
+				      * ecryptfs_message_buf_len), GFP_KERNEL);
+	if (!ecryptfs_msg_ctx_arr) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+		goto out;
+	}
+	mutex_init(&ecryptfs_msg_ctx_lists_mux);
+	mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+	ecryptfs_msg_counter = 0;
+	for (i = 0; i < ecryptfs_message_buf_len; i++) {
+		INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node);
+		mutex_init(&ecryptfs_msg_ctx_arr[i].mux);
+		mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);
+		ecryptfs_msg_ctx_arr[i].index = i;
+		ecryptfs_msg_ctx_arr[i].state = ECRYPTFS_MSG_CTX_STATE_FREE;
+		ecryptfs_msg_ctx_arr[i].counter = 0;
+		ecryptfs_msg_ctx_arr[i].task = NULL;
+		ecryptfs_msg_ctx_arr[i].msg = NULL;
+		list_add_tail(&ecryptfs_msg_ctx_arr[i].node,
+			      &ecryptfs_msg_ctx_free_list);
+		mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux);
+	}
+	mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+	switch(transport) {
+	case ECRYPTFS_TRANSPORT_NETLINK:
+		rc = ecryptfs_init_netlink();
+		if (rc)
+			ecryptfs_release_messaging(transport);
+		break;
+	case ECRYPTFS_TRANSPORT_CONNECTOR:
+	case ECRYPTFS_TRANSPORT_RELAYFS:
+	default:
+		rc = -ENOSYS;
+	}
+out:
+	return rc;
+}
+
+void ecryptfs_release_messaging(unsigned int transport)
+{
+	if (ecryptfs_msg_ctx_arr) {
+		int i;
+
+		mutex_lock(&ecryptfs_msg_ctx_lists_mux);
+		for (i = 0; i < ecryptfs_message_buf_len; i++) {
+			mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);
+			if (ecryptfs_msg_ctx_arr[i].msg)
+				kfree(ecryptfs_msg_ctx_arr[i].msg);
+			mutex_unlock(&ecryptfs_msg_ctx_arr[i].mux);
+		}
+		kfree(ecryptfs_msg_ctx_arr);
+		mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
+	}
+	if (ecryptfs_daemon_id_hash) {
+		struct hlist_node *elem;
+		struct ecryptfs_daemon_id *id;
+		int i;
+
+		mutex_lock(&ecryptfs_daemon_id_hash_mux);
+		for (i = 0; i < ecryptfs_hash_buckets; i++) {
+			hlist_for_each_entry(id, elem,
+					     &ecryptfs_daemon_id_hash[i],
+					     id_chain) {
+				hlist_del(elem);
+				kfree(id);
+			}
+		}
+		kfree(ecryptfs_daemon_id_hash);
+		mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+	}
+	switch(transport) {
+	case ECRYPTFS_TRANSPORT_NETLINK:
+		ecryptfs_release_netlink();
+		break;
+	case ECRYPTFS_TRANSPORT_CONNECTOR:
+	case ECRYPTFS_TRANSPORT_RELAYFS:
+	default:
+		break;
+	}
+	return;
+}
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 06843d2..3a6f65c 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -6,7 +6,7 @@
  *
  * Copyright (C) 1997-2003 Erez Zadok
  * Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -234,22 +234,13 @@
 		goto out;
 	}
 	wait_on_page_locked(lower_page);
-	page_data = (char *)kmap(page);
-	if (!page_data) {
-		rc = -ENOMEM;
-		ecryptfs_printk(KERN_ERR, "Error mapping page\n");
-		goto out;
-	}
-	lower_page_data = (char *)kmap(lower_page);
-	if (!lower_page_data) {
-		rc = -ENOMEM;
-		ecryptfs_printk(KERN_ERR, "Error mapping page\n");
-		kunmap(page);
-		goto out;
-	}
+	page_data = kmap_atomic(page, KM_USER0);
+	lower_page_data = kmap_atomic(lower_page, KM_USER1);
 	memcpy(page_data, lower_page_data, PAGE_CACHE_SIZE);
-	kunmap(lower_page);
-	kunmap(page);
+	kunmap_atomic(lower_page_data, KM_USER1);
+	flush_dcache_page(lower_page);
+	kunmap_atomic(page_data, KM_USER0);
+	flush_dcache_page(page);
 	rc = 0;
 out:
 	if (likely(lower_page))
@@ -260,6 +251,33 @@
 		ClearPageUptodate(page);
 	return rc;
 }
+/**
+ *   Header Extent:
+ *     Octets 0-7:        Unencrypted file size (big-endian)
+ *     Octets 8-15:       eCryptfs special marker
+ *     Octets 16-19:      Flags
+ *      Octet 16:         File format version number (between 0 and 255)
+ *      Octets 17-18:     Reserved
+ *      Octet 19:         Bit 1 (lsb): Reserved
+ *                        Bit 2: Encrypted?
+ *                        Bits 3-8: Reserved
+ *     Octets 20-23:      Header extent size (big-endian)
+ *     Octets 24-25:      Number of header extents at front of file
+ *                        (big-endian)
+ *     Octet  26:         Begin RFC 2440 authentication token packet set
+ */
+static void set_header_info(char *page_virt,
+			    struct ecryptfs_crypt_stat *crypt_stat)
+{
+	size_t written;
+	int save_num_header_extents_at_front =
+		crypt_stat->num_header_extents_at_front;
+
+	crypt_stat->num_header_extents_at_front = 1;
+	ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written);
+	crypt_stat->num_header_extents_at_front =
+		save_num_header_extents_at_front;
+}
 
 /**
  * ecryptfs_readpage
@@ -279,8 +297,8 @@
 	crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
 			->crypt_stat;
 	if (!crypt_stat
-	    || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)
-	    || ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+	    || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
+	    || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
 		ecryptfs_printk(KERN_DEBUG,
 				"Passing through unencrypted page\n");
 		rc = ecryptfs_do_readpage(file, page, page->index);
@@ -289,10 +307,51 @@
 					"[%d]\n", rc);
 			goto out;
 		}
+	} else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
+		if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
+			int num_pages_in_header_region =
+				(crypt_stat->header_extent_size
+				 / PAGE_CACHE_SIZE);
+
+			if (page->index < num_pages_in_header_region) {
+				char *page_virt;
+
+				page_virt = kmap_atomic(page, KM_USER0);
+				memset(page_virt, 0, PAGE_CACHE_SIZE);
+				if (page->index == 0) {
+					rc = ecryptfs_read_xattr_region(
+						page_virt, file->f_path.dentry);
+					set_header_info(page_virt, crypt_stat);
+				}
+				kunmap_atomic(page_virt, KM_USER0);
+				flush_dcache_page(page);
+				if (rc) {
+					printk(KERN_ERR "Error reading xattr "
+					       "region\n");
+					goto out;
+				}
+			} else {
+				rc = ecryptfs_do_readpage(
+					file, page,
+					(page->index
+					 - num_pages_in_header_region));
+				if (rc) {
+					printk(KERN_ERR "Error reading page; "
+					       "rc = [%d]\n", rc);
+					goto out;
+				}
+			}
+		} else {
+			rc = ecryptfs_do_readpage(file, page, page->index);
+			if (rc) {
+				printk(KERN_ERR "Error reading page; rc = "
+				       "[%d]\n", rc);
+				goto out;
+			}
+		}
 	} else {
 		rc = ecryptfs_decrypt_page(file, page);
 		if (rc) {
-
 			ecryptfs_printk(KERN_ERR, "Error decrypting page; "
 					"rc = [%d]\n", rc);
 			goto out;
@@ -308,30 +367,27 @@
 	return rc;
 }
 
+/**
+ * Called with lower inode mutex held.
+ */
 static int fill_zeros_to_end_of_page(struct page *page, unsigned int to)
 {
 	struct inode *inode = page->mapping->host;
 	int end_byte_in_page;
-	int rc = 0;
 	char *page_virt;
 
-	if ((i_size_read(inode) / PAGE_CACHE_SIZE) == page->index) {
-		end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
-		if (to > end_byte_in_page)
-			end_byte_in_page = to;
-		page_virt = kmap(page);
-		if (!page_virt) {
-			rc = -ENOMEM;
-			ecryptfs_printk(KERN_WARNING,
-					"Could not map page\n");
-			goto out;
-		}
-		memset((page_virt + end_byte_in_page), 0,
-		       (PAGE_CACHE_SIZE - end_byte_in_page));
-		kunmap(page);
-	}
+	if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index)
+		goto out;
+	end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
+	if (to > end_byte_in_page)
+		end_byte_in_page = to;
+	page_virt = kmap_atomic(page, KM_USER0);
+	memset((page_virt + end_byte_in_page), 0,
+	       (PAGE_CACHE_SIZE - end_byte_in_page));
+	kunmap_atomic(page_virt, KM_USER0);
+	flush_dcache_page(page);
 out:
-	return rc;
+	return 0;
 }
 
 static int ecryptfs_prepare_write(struct file *file, struct page *page,
@@ -339,7 +395,6 @@
 {
 	int rc = 0;
 
-	kmap(page);
 	if (from == 0 && to == PAGE_CACHE_SIZE)
 		goto out;	/* If we are writing a full page, it will be
 				   up to date. */
@@ -349,30 +404,6 @@
 	return rc;
 }
 
-int ecryptfs_grab_and_map_lower_page(struct page **lower_page,
-				     char **lower_virt,
-				     struct inode *lower_inode,
-				     unsigned long lower_page_index)
-{
-	int rc = 0;
-
-	(*lower_page) = grab_cache_page(lower_inode->i_mapping,
-					lower_page_index);
-	if (!(*lower_page)) {
-		ecryptfs_printk(KERN_ERR, "grab_cache_page for "
-				"lower_page_index = [0x%.16x] failed\n",
-				lower_page_index);
-		rc = -EINVAL;
-		goto out;
-	}
-	if (lower_virt)
-		(*lower_virt) = kmap((*lower_page));
-	else
-		kmap((*lower_page));
-out:
-	return rc;
-}
-
 int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
 					      struct inode *lower_inode,
 					      struct writeback_control *wbc)
@@ -391,11 +422,8 @@
 	return rc;
 }
 
-static void ecryptfs_unmap_and_release_lower_page(struct page *lower_page)
+static void ecryptfs_release_lower_page(struct page *lower_page)
 {
-	kunmap(lower_page);
-	ecryptfs_printk(KERN_DEBUG, "Unlocking lower page with index = "
-			"[0x%.16x]\n", lower_page->index);
 	unlock_page(lower_page);
 	page_cache_release(lower_page);
 }
@@ -407,10 +435,9 @@
  *
  * Returns zero on success; non-zero on error.
  */
-int
-ecryptfs_write_inode_size_to_header(struct file *lower_file,
-				    struct inode *lower_inode,
-				    struct inode *inode)
+static int ecryptfs_write_inode_size_to_header(struct file *lower_file,
+					       struct inode *lower_inode,
+					       struct inode *inode)
 {
 	int rc = 0;
 	struct page *header_page;
@@ -418,11 +445,11 @@
 	const struct address_space_operations *lower_a_ops;
 	u64 file_size;
 
-	rc = ecryptfs_grab_and_map_lower_page(&header_page, &header_virt,
-					      lower_inode, 0);
-	if (rc) {
-		ecryptfs_printk(KERN_ERR, "grab_cache_page for header page "
-				"failed\n");
+	header_page = grab_cache_page(lower_inode->i_mapping, 0);
+	if (!header_page) {
+		ecryptfs_printk(KERN_ERR, "grab_cache_page for "
+				"lower_page_index 0 failed\n");
+		rc = -EINVAL;
 		goto out;
 	}
 	lower_a_ops = lower_inode->i_mapping->a_ops;
@@ -430,18 +457,95 @@
 	file_size = (u64)i_size_read(inode);
 	ecryptfs_printk(KERN_DEBUG, "Writing size: [0x%.16x]\n", file_size);
 	file_size = cpu_to_be64(file_size);
+	header_virt = kmap_atomic(header_page, KM_USER0);
 	memcpy(header_virt, &file_size, sizeof(u64));
+	kunmap_atomic(header_virt, KM_USER0);
+	flush_dcache_page(header_page);
 	rc = lower_a_ops->commit_write(lower_file, header_page, 0, 8);
 	if (rc < 0)
 		ecryptfs_printk(KERN_ERR, "Error commiting header page "
 				"write\n");
-	ecryptfs_unmap_and_release_lower_page(header_page);
+	ecryptfs_release_lower_page(header_page);
 	lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
 	mark_inode_dirty_sync(inode);
 out:
 	return rc;
 }
 
+static int ecryptfs_write_inode_size_to_xattr(struct inode *lower_inode,
+					      struct inode *inode,
+					      struct dentry *ecryptfs_dentry,
+					      int lower_i_mutex_held)
+{
+	ssize_t size;
+	void *xattr_virt;
+	struct dentry *lower_dentry;
+	u64 file_size;
+	int rc;
+
+	xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
+	if (!xattr_virt) {
+		printk(KERN_ERR "Out of memory whilst attempting to write "
+		       "inode size to xattr\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
+	if (!lower_dentry->d_inode->i_op->getxattr) {
+		printk(KERN_WARNING
+		       "No support for setting xattr in lower filesystem\n");
+		rc = -ENOSYS;
+		kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
+		goto out;
+	}
+	if (!lower_i_mutex_held)
+		mutex_lock(&lower_dentry->d_inode->i_mutex);
+	size = lower_dentry->d_inode->i_op->getxattr(lower_dentry,
+						     ECRYPTFS_XATTR_NAME,
+						     xattr_virt,
+						     PAGE_CACHE_SIZE);
+	if (!lower_i_mutex_held)
+		mutex_unlock(&lower_dentry->d_inode->i_mutex);
+	if (size < 0)
+		size = 8;
+	file_size = (u64)i_size_read(inode);
+	file_size = cpu_to_be64(file_size);
+	memcpy(xattr_virt, &file_size, sizeof(u64));
+	if (!lower_i_mutex_held)
+		mutex_lock(&lower_dentry->d_inode->i_mutex);
+	rc = lower_dentry->d_inode->i_op->setxattr(lower_dentry,
+						   ECRYPTFS_XATTR_NAME,
+						   xattr_virt, size, 0);
+	if (!lower_i_mutex_held)
+		mutex_unlock(&lower_dentry->d_inode->i_mutex);
+	if (rc)
+		printk(KERN_ERR "Error whilst attempting to write inode size "
+		       "to lower file xattr; rc = [%d]\n", rc);
+	kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
+out:
+	return rc;
+}
+
+int
+ecryptfs_write_inode_size_to_metadata(struct file *lower_file,
+				      struct inode *lower_inode,
+				      struct inode *inode,
+				      struct dentry *ecryptfs_dentry,
+				      int lower_i_mutex_held)
+{
+	struct ecryptfs_crypt_stat *crypt_stat;
+
+	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+		return ecryptfs_write_inode_size_to_xattr(lower_inode, inode,
+							  ecryptfs_dentry,
+							  lower_i_mutex_held);
+	else
+		return ecryptfs_write_inode_size_to_header(lower_file,
+							   lower_inode,
+							   inode);
+}
+
 int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
 			    struct file *lower_file,
 			    unsigned long lower_page_index, int byte_offset,
@@ -449,10 +553,10 @@
 {
 	int rc = 0;
 
-	rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL, lower_inode,
-					      lower_page_index);
-	if (rc) {
-		ecryptfs_printk(KERN_ERR, "Error attempting to grab and map "
+	*lower_page = grab_cache_page(lower_inode->i_mapping, lower_page_index);
+	if (!(*lower_page)) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_ERR, "Error attempting to grab "
 				"lower page with index [0x%.16x]\n",
 				lower_page_index);
 		goto out;
@@ -468,7 +572,7 @@
 	}
 out:
 	if (rc && (*lower_page)) {
-		ecryptfs_unmap_and_release_lower_page(*lower_page);
+		ecryptfs_release_lower_page(*lower_page);
 		(*lower_page) = NULL;
 	}
 	return rc;
@@ -493,7 +597,7 @@
 				"Error committing write; rc = [%d]\n", rc);
 	} else
 		rc = 0;
-	ecryptfs_unmap_and_release_lower_page(lower_page);
+	ecryptfs_release_lower_page(lower_page);
 	return rc;
 }
 
@@ -528,89 +632,7 @@
 	return rc;
 }
 
-static int
-process_new_file(struct ecryptfs_crypt_stat *crypt_stat,
-		 struct file *file, struct inode *inode)
-{
-	struct page *header_page;
-	const struct address_space_operations *lower_a_ops;
-	struct inode *lower_inode;
-	struct file *lower_file;
-	char *header_virt;
-	int rc = 0;
-	int current_header_page = 0;
-	int header_pages;
-	int more_header_data_to_be_written = 1;
-
-	lower_inode = ecryptfs_inode_to_lower(inode);
-	lower_file = ecryptfs_file_to_lower(file);
-	lower_a_ops = lower_inode->i_mapping->a_ops;
-	header_pages = ((crypt_stat->header_extent_size
-			 * crypt_stat->num_header_extents_at_front)
-			/ PAGE_CACHE_SIZE);
-	BUG_ON(header_pages < 1);
-	while (current_header_page < header_pages) {
-		rc = ecryptfs_grab_and_map_lower_page(&header_page,
-						      &header_virt,
-						      lower_inode,
-						      current_header_page);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "grab_cache_page for "
-					"header page [%d] failed; rc = [%d]\n",
-					current_header_page, rc);
-			goto out;
-		}
-		rc = lower_a_ops->prepare_write(lower_file, header_page, 0,
-						PAGE_CACHE_SIZE);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "Error preparing to write "
-					"header page out; rc = [%d]\n", rc);
-			goto out;
-		}
-		memset(header_virt, 0, PAGE_CACHE_SIZE);
-		if (more_header_data_to_be_written) {
-			rc = ecryptfs_write_headers_virt(header_virt,
-							 crypt_stat,
-							 file->f_dentry);
-			if (rc) {
-				ecryptfs_printk(KERN_WARNING, "Error "
-						"generating header; rc = "
-						"[%d]\n", rc);
-				rc = -EIO;
-				memset(header_virt, 0, PAGE_CACHE_SIZE);
-				ecryptfs_unmap_and_release_lower_page(
-					header_page);
-				goto out;
-			}
-			if (current_header_page == 0)
-				memset(header_virt, 0, 8);
-			more_header_data_to_be_written = 0;
-		}
-		rc = lower_a_ops->commit_write(lower_file, header_page, 0,
-					       PAGE_CACHE_SIZE);
-		ecryptfs_unmap_and_release_lower_page(header_page);
-		if (rc < 0) {
-			ecryptfs_printk(KERN_ERR,
-					"Error commiting header page write; "
-					"rc = [%d]\n", rc);
-			break;
-		}
-		current_header_page++;
-	}
-	if (rc >= 0) {
-		rc = 0;
-		ecryptfs_printk(KERN_DEBUG, "lower_inode->i_blocks = "
-				"[0x%.16x]\n", lower_inode->i_blocks);
-		i_size_write(inode, 0);
-		lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
-		mark_inode_dirty_sync(inode);
-	}
-	ecryptfs_printk(KERN_DEBUG, "Clearing ECRYPTFS_NEW_FILE flag in "
-			"crypt_stat at memory location [%p]\n", crypt_stat);
-	ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
-out:
-	return rc;
-}
+struct kmem_cache *ecryptfs_xattr_cache;
 
 /**
  * ecryptfs_commit_write
@@ -640,15 +662,10 @@
 	mutex_lock(&lower_inode->i_mutex);
 	crypt_stat = &ecryptfs_inode_to_private(file->f_path.dentry->d_inode)
 				->crypt_stat;
-	if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
+	if (crypt_stat->flags & ECRYPTFS_NEW_FILE) {
 		ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
 			"crypt_stat at memory location [%p]\n", crypt_stat);
-		rc = process_new_file(crypt_stat, file, inode);
-		if (rc) {
-			ecryptfs_printk(KERN_ERR, "Error processing new "
-					"file; rc = [%d]\n", rc);
-			goto out;
-		}
+		crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE);
 	} else
 		ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
 	ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
@@ -670,7 +687,6 @@
 				"index [0x%.16x])\n", page->index);
 		goto out;
 	}
-	rc = 0;
 	inode->i_blocks = lower_inode->i_blocks;
 	pos = (page->index << PAGE_CACHE_SHIFT) + to;
 	if (pos > i_size_read(inode)) {
@@ -678,11 +694,15 @@
 		ecryptfs_printk(KERN_DEBUG, "Expanded file size to "
 				"[0x%.16x]\n", i_size_read(inode));
 	}
-	ecryptfs_write_inode_size_to_header(lower_file, lower_inode, inode);
+	rc = ecryptfs_write_inode_size_to_metadata(lower_file, lower_inode,
+						   inode, file->f_dentry,
+						   ECRYPTFS_LOWER_I_MUTEX_HELD);
+	if (rc)
+		printk(KERN_ERR "Error writing inode size to metadata; "
+		       "rc = [%d]\n", rc);
 	lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
 	mark_inode_dirty_sync(inode);
 out:
-	kunmap(page); /* mapped in prior call (prepare_write) */
 	if (rc < 0)
 		ClearPageUptodate(page);
 	else
@@ -707,6 +727,7 @@
 {
 	int rc = 0;
 	struct page *tmp_page;
+	char *tmp_page_virt;
 
 	tmp_page = ecryptfs_get1page(file, index);
 	if (IS_ERR(tmp_page)) {
@@ -715,28 +736,27 @@
 		rc = PTR_ERR(tmp_page);
 		goto out;
 	}
-	kmap(tmp_page);
 	rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros);
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
 				"to remainder of page at index [0x%.16x]\n",
 				index);
-		kunmap(tmp_page);
 		page_cache_release(tmp_page);
 		goto out;
 	}
-	memset(((char *)page_address(tmp_page) + start), 0, num_zeros);
+	tmp_page_virt = kmap_atomic(tmp_page, KM_USER0);
+	memset(((char *)tmp_page_virt + start), 0, num_zeros);
+	kunmap_atomic(tmp_page_virt, KM_USER0);
+	flush_dcache_page(tmp_page);
 	rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros);
 	if (rc < 0) {
 		ecryptfs_printk(KERN_ERR, "Error attempting to write zero's "
 				"to remainder of page at index [0x%.16x]\n",
 				index);
-		kunmap(tmp_page);
 		page_cache_release(tmp_page);
 		goto out;
 	}
 	rc = 0;
-	kunmap(tmp_page);
 	page_cache_release(tmp_page);
 out:
 	return rc;
diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c
new file mode 100644
index 0000000..e3aa225
--- /dev/null
+++ b/fs/ecryptfs/netlink.c
@@ -0,0 +1,255 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2004-2006 International Business Machines Corp.
+ *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
+ *		Tyler Hicks <tyhicks@ou.edu>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <net/sock.h>
+#include <linux/hash.h>
+#include <linux/random.h>
+#include "ecryptfs_kernel.h"
+
+static struct sock *ecryptfs_nl_sock;
+
+/**
+ * ecryptfs_send_netlink
+ * @data: The data to include as the payload
+ * @data_len: The byte count of the data
+ * @msg_ctx: The netlink context that will be used to handle the
+ *          response message
+ * @msg_type: The type of netlink message to send
+ * @msg_flags: The flags to include in the netlink header
+ * @daemon_pid: The process id of the daemon to send the message to
+ *
+ * Sends the data to the specified daemon pid and uses the netlink
+ * context element to store the data needed for validation upon
+ * receiving the response.  The data and the netlink context can be
+ * null if just sending a netlink header is sufficient.  Returns zero
+ * upon sending the message; non-zero upon error.
+ */
+int ecryptfs_send_netlink(char *data, int data_len,
+			  struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
+			  u16 msg_flags, pid_t daemon_pid)
+{
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	struct ecryptfs_message *msg;
+	size_t payload_len;
+	int rc;
+
+	payload_len = ((data && data_len) ? (sizeof(*msg) + data_len) : 0);
+	skb = alloc_skb(NLMSG_SPACE(payload_len), GFP_KERNEL);
+	if (!skb) {
+		rc = -ENOMEM;
+		ecryptfs_printk(KERN_ERR, "Failed to allocate socket buffer\n");
+		goto out;
+	}
+	nlh = NLMSG_PUT(skb, daemon_pid, msg_ctx ? msg_ctx->counter : 0,
+			msg_type, payload_len);
+	nlh->nlmsg_flags = msg_flags;
+	if (msg_ctx && payload_len) {
+		msg = (struct ecryptfs_message *)NLMSG_DATA(nlh);
+		msg->index = msg_ctx->index;
+		msg->data_len = data_len;
+		memcpy(msg->data, data, data_len);
+	}
+	rc = netlink_unicast(ecryptfs_nl_sock, skb, daemon_pid, 0);
+	if (rc < 0) {
+		ecryptfs_printk(KERN_ERR, "Failed to send eCryptfs netlink "
+				"message; rc = [%d]\n", rc);
+		goto out;
+	}
+	rc = 0;
+	goto out;
+nlmsg_failure:
+	rc = -EMSGSIZE;
+	kfree_skb(skb);
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_process_nl_reponse
+ * @skb: The socket buffer containing the netlink message of state
+ *       RESPONSE
+ *
+ * Processes a response message after sending a operation request to
+ * userspace.  Attempts to assign the msg to a netlink context element
+ * at the index specified in the msg.  The sk_buff and nlmsghdr must
+ * be validated before this function. Returns zero upon delivery to
+ * desired context element; non-zero upon delivery failure or error.
+ */
+static int ecryptfs_process_nl_response(struct sk_buff *skb)
+{
+	struct nlmsghdr *nlh = (struct nlmsghdr*)skb->data;
+	struct ecryptfs_message *msg = NLMSG_DATA(nlh);
+	int rc;
+
+	if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) {
+		rc = -EINVAL;
+		ecryptfs_printk(KERN_ERR, "Received netlink message with "
+				"incorrectly specified data length\n");
+		goto out;
+	}
+	rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid,
+				       NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq);
+	if (rc)
+		printk(KERN_ERR
+		       "Error processing response message; rc = [%d]\n", rc);
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_process_nl_helo
+ * @skb: The socket buffer containing the nlmsghdr in HELO state
+ *
+ * Gets uid and pid of the skb and adds the values to the daemon id
+ * hash. Returns zero after adding a new daemon id to the hash list;
+ * non-zero otherwise.
+ */
+static int ecryptfs_process_nl_helo(struct sk_buff *skb)
+{
+	int rc;
+
+	rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK,
+				   NETLINK_CREDS(skb)->uid,
+				   NETLINK_CREDS(skb)->pid);
+	if (rc)
+		printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
+	return rc;
+}
+
+/**
+ * ecryptfs_process_nl_quit
+ * @skb: The socket buffer containing the nlmsghdr in QUIT state
+ *
+ * Gets uid and pid of the skb and deletes the corresponding daemon
+ * id, if it is the registered that is requesting the
+ * deletion. Returns zero after deleting the desired daemon id;
+ * non-zero otherwise.
+ */
+static int ecryptfs_process_nl_quit(struct sk_buff *skb)
+{
+	int rc;
+
+	rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid,
+				   NETLINK_CREDS(skb)->pid);
+	if (rc)
+		printk(KERN_WARNING
+		       "Error processing QUIT message; rc = [%d]\n", rc);
+	return rc;
+}
+
+/**
+ * ecryptfs_receive_nl_message
+ *
+ * Callback function called by netlink system when a message arrives.
+ * If the message looks to be valid, then an attempt is made to assign
+ * it to its desired netlink context element and wake up the process
+ * that is waiting for a response.
+ */
+static void ecryptfs_receive_nl_message(struct sock *sk, int len)
+{
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	int rc = 0;	/* skb_recv_datagram requires this */
+
+receive:
+	skb = skb_recv_datagram(sk, 0, 0, &rc);
+	if (rc == -EINTR)
+		goto receive;
+	else if (rc < 0) {
+		ecryptfs_printk(KERN_ERR, "Error occurred while "
+				"receiving eCryptfs netlink message; "
+				"rc = [%d]\n", rc);
+		return;
+	}
+	nlh = (struct nlmsghdr *)skb->data;
+	if (!NLMSG_OK(nlh, skb->len)) {
+		ecryptfs_printk(KERN_ERR, "Received corrupt netlink "
+				"message\n");
+		goto free;
+	}
+	switch (nlh->nlmsg_type) {
+		case ECRYPTFS_NLMSG_RESPONSE:
+			if (ecryptfs_process_nl_response(skb)) {
+				ecryptfs_printk(KERN_WARNING, "Failed to "
+						"deliver netlink response to "
+						"requesting operation\n");
+			}
+			break;
+		case ECRYPTFS_NLMSG_HELO:
+			if (ecryptfs_process_nl_helo(skb)) {
+				ecryptfs_printk(KERN_WARNING, "Failed to "
+						"fulfill HELO request\n");
+			}
+			break;
+		case ECRYPTFS_NLMSG_QUIT:
+			if (ecryptfs_process_nl_quit(skb)) {
+				ecryptfs_printk(KERN_WARNING, "Failed to "
+						"fulfill QUIT request\n");
+			}
+			break;
+		default:
+			ecryptfs_printk(KERN_WARNING, "Dropping netlink "
+					"message of unrecognized type [%d]\n",
+					nlh->nlmsg_type);
+			break;
+	}
+free:
+	kfree_skb(skb);
+}
+
+/**
+ * ecryptfs_init_netlink
+ *
+ * Initializes the daemon id hash list, netlink context array, and
+ * necessary locks.  Returns zero upon success; non-zero upon error.
+ */
+int ecryptfs_init_netlink(void)
+{
+	int rc;
+
+	ecryptfs_nl_sock = netlink_kernel_create(NETLINK_ECRYPTFS, 0,
+						 ecryptfs_receive_nl_message,
+						 THIS_MODULE);
+	if (!ecryptfs_nl_sock) {
+		rc = -EIO;
+		ecryptfs_printk(KERN_ERR, "Failed to create netlink socket\n");
+		goto out;
+	}
+	ecryptfs_nl_sock->sk_sndtimeo = ECRYPTFS_DEFAULT_SEND_TIMEOUT;
+	rc = 0;
+out:
+	return rc;
+}
+
+/**
+ * ecryptfs_release_netlink
+ *
+ * Frees all memory used by the netlink context array and releases the
+ * netlink socket.
+ */
+void ecryptfs_release_netlink(void)
+{
+	if (ecryptfs_nl_sock && ecryptfs_nl_sock->sk_socket)
+		sock_release(ecryptfs_nl_sock->sk_socket);
+	ecryptfs_nl_sock = NULL;
+}
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index eaa5daa..7b3f0cc 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -168,7 +168,7 @@
 	return rc;
 }
 
-struct super_operations ecryptfs_sops = {
+const struct super_operations ecryptfs_sops = {
 	.alloc_inode = ecryptfs_alloc_inode,
 	.destroy_inode = ecryptfs_destroy_inode,
 	.drop_inode = generic_delete_inode,
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index b46c488..dfb5cb4 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -15,7 +15,7 @@
 	.readdir	= efs_readdir,
 };
 
-struct inode_operations efs_dir_inode_operations = {
+const struct inode_operations efs_dir_inode_operations = {
 	.lookup		= efs_lookup,
 };
 
diff --git a/fs/efs/super.c b/fs/efs/super.c
index dfebf21..c2235e4 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -105,7 +105,7 @@
 	return 0;
 }
 
-static struct super_operations efs_superblock_operations = {
+static const struct super_operations efs_superblock_operations = {
 	.alloc_inode	= efs_alloc_inode,
 	.destroy_inode	= efs_destroy_inode,
 	.read_inode	= efs_read_inode,
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index c19ac15..e2a0ea5 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -158,7 +158,7 @@
 extern const struct file_operations ext2_dir_operations;
 
 /* file.c */
-extern struct inode_operations ext2_file_inode_operations;
+extern const struct inode_operations ext2_file_inode_operations;
 extern const struct file_operations ext2_file_operations;
 extern const struct file_operations ext2_xip_file_operations;
 
@@ -168,9 +168,9 @@
 extern const struct address_space_operations ext2_nobh_aops;
 
 /* namei.c */
-extern struct inode_operations ext2_dir_inode_operations;
-extern struct inode_operations ext2_special_inode_operations;
+extern const struct inode_operations ext2_dir_inode_operations;
+extern const struct inode_operations ext2_special_inode_operations;
 
 /* symlink.c */
-extern struct inode_operations ext2_fast_symlink_inode_operations;
-extern struct inode_operations ext2_symlink_inode_operations;
+extern const struct inode_operations ext2_fast_symlink_inode_operations;
+extern const struct inode_operations ext2_symlink_inode_operations;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 2dba473..566d4e2 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -75,7 +75,7 @@
 };
 #endif
 
-struct inode_operations ext2_file_inode_operations = {
+const struct inode_operations ext2_file_inode_operations = {
 	.truncate	= ext2_truncate,
 #ifdef CONFIG_EXT2_FS_XATTR
 	.setxattr	= generic_setxattr,
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index e1af5b4..e69beed 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -373,7 +373,7 @@
 	return err;
 }
 
-struct inode_operations ext2_dir_inode_operations = {
+const struct inode_operations ext2_dir_inode_operations = {
 	.create		= ext2_create,
 	.lookup		= ext2_lookup,
 	.link		= ext2_link,
@@ -393,7 +393,7 @@
 	.permission	= ext2_permission,
 };
 
-struct inode_operations ext2_special_inode_operations = {
+const struct inode_operations ext2_special_inode_operations = {
 #ifdef CONFIG_EXT2_FS_XATTR
 	.setxattr	= generic_setxattr,
 	.getxattr	= generic_getxattr,
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index daaa243..a046a41 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -231,7 +231,7 @@
 static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);
 #endif
 
-static struct super_operations ext2_sops = {
+static const struct super_operations ext2_sops = {
 	.alloc_inode	= ext2_alloc_inode,
 	.destroy_inode	= ext2_destroy_inode,
 	.read_inode	= ext2_read_inode,
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c
index 1e67d87..4e2426e 100644
--- a/fs/ext2/symlink.c
+++ b/fs/ext2/symlink.c
@@ -28,7 +28,7 @@
 	return NULL;
 }
 
-struct inode_operations ext2_symlink_inode_operations = {
+const struct inode_operations ext2_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -40,7 +40,7 @@
 #endif
 };
  
-struct inode_operations ext2_fast_symlink_inode_operations = {
+const struct inode_operations ext2_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= ext2_follow_link,
 #ifdef CONFIG_EXT2_FS_XATTR
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 881f636..1e6f138 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -125,7 +125,7 @@
 	.splice_write	= generic_file_splice_write,
 };
 
-struct inode_operations ext3_file_inode_operations = {
+const struct inode_operations ext3_file_inode_operations = {
 	.truncate	= ext3_truncate,
 	.setattr	= ext3_setattr,
 #ifdef CONFIG_EXT3_FS_XATTR
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index a8e8932..49159f1 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -2365,7 +2365,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations ext3_dir_inode_operations = {
+const struct inode_operations ext3_dir_inode_operations = {
 	.create		= ext3_create,
 	.lookup		= ext3_lookup,
 	.link		= ext3_link,
@@ -2385,7 +2385,7 @@
 	.permission	= ext3_permission,
 };
 
-struct inode_operations ext3_special_inode_operations = {
+const struct inode_operations ext3_special_inode_operations = {
 	.setattr	= ext3_setattr,
 #ifdef CONFIG_EXT3_FS_XATTR
 	.setxattr	= generic_setxattr,
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index a0623a8..4a4fcd6 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -639,7 +639,7 @@
 };
 #endif
 
-static struct super_operations ext3_sops = {
+static const struct super_operations ext3_sops = {
 	.alloc_inode	= ext3_alloc_inode,
 	.destroy_inode	= ext3_destroy_inode,
 	.read_inode	= ext3_read_inode,
diff --git a/fs/ext3/symlink.c b/fs/ext3/symlink.c
index 4f79122..ff7b4cc 100644
--- a/fs/ext3/symlink.c
+++ b/fs/ext3/symlink.c
@@ -30,7 +30,7 @@
 	return NULL;
 }
 
-struct inode_operations ext3_symlink_inode_operations = {
+const struct inode_operations ext3_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -42,7 +42,7 @@
 #endif
 };
 
-struct inode_operations ext3_fast_symlink_inode_operations = {
+const struct inode_operations ext3_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= ext3_follow_link,
 #ifdef CONFIG_EXT3_FS_XATTR
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 3bbc24b..3c6c1fd 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -125,7 +125,7 @@
 	.splice_write	= generic_file_splice_write,
 };
 
-struct inode_operations ext4_file_inode_operations = {
+const struct inode_operations ext4_file_inode_operations = {
 	.truncate	= ext4_truncate,
 	.setattr	= ext4_setattr,
 #ifdef CONFIG_EXT4DEV_FS_XATTR
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 34b3448..e7e1d79 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2363,7 +2363,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations ext4_dir_inode_operations = {
+const struct inode_operations ext4_dir_inode_operations = {
 	.create		= ext4_create,
 	.lookup		= ext4_lookup,
 	.link		= ext4_link,
@@ -2383,7 +2383,7 @@
 	.permission	= ext4_permission,
 };
 
-struct inode_operations ext4_special_inode_operations = {
+const struct inode_operations ext4_special_inode_operations = {
 	.setattr	= ext4_setattr,
 #ifdef CONFIG_EXT4DEV_FS_XATTR
 	.setxattr	= generic_setxattr,
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index c63a18b..61c4718 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -690,7 +690,7 @@
 };
 #endif
 
-static struct super_operations ext4_sops = {
+static const struct super_operations ext4_sops = {
 	.alloc_inode	= ext4_alloc_inode,
 	.destroy_inode	= ext4_destroy_inode,
 	.read_inode	= ext4_read_inode,
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index fcf5272..e6f9da4 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -30,7 +30,7 @@
 	return NULL;
 }
 
-struct inode_operations ext4_symlink_inode_operations = {
+const struct inode_operations ext4_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -42,7 +42,7 @@
 #endif
 };
 
-struct inode_operations ext4_fast_symlink_inode_operations = {
+const struct inode_operations ext4_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= ext4_follow_link,
 #ifdef CONFIG_EXT4DEV_FS_XATTR
diff --git a/fs/fat/file.c b/fs/fat/file.c
index c1237b7..55d3c74 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -312,7 +312,7 @@
 }
 EXPORT_SYMBOL_GPL(fat_getattr);
 
-struct inode_operations fat_file_inode_operations = {
+const struct inode_operations fat_file_inode_operations = {
 	.truncate	= fat_truncate,
 	.setattr	= fat_notify_change,
 	.getattr	= fat_getattr,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index a9e4688..7610735 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -618,7 +618,7 @@
 EXPORT_SYMBOL_GPL(fat_sync_inode);
 
 static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);
-static struct super_operations fat_sops = {
+static const struct super_operations fat_sops = {
 	.alloc_inode	= fat_alloc_inode,
 	.destroy_inode	= fat_destroy_inode,
 	.write_inode	= fat_write_inode,
@@ -1151,7 +1151,7 @@
  * Read the super block of an MS-DOS FS.
  */
 int fat_fill_super(struct super_block *sb, void *data, int silent,
-		   struct inode_operations *fs_dir_inode_ops, int isvfat)
+		   const struct inode_operations *fs_dir_inode_ops, int isvfat)
 {
 	struct inode *root_inode = NULL;
 	struct buffer_head *bh;
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 1cf1fe8..91ccee8 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -62,7 +62,7 @@
 extern void			vxfs_clear_inode(struct inode *);
 
 /* vxfs_lookup.c */
-extern struct inode_operations	vxfs_dir_inode_ops;
+extern const struct inode_operations	vxfs_dir_inode_ops;
 extern const struct file_operations	vxfs_dir_operations;
 
 /* vxfs_olt.c */
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
index 4e25f3f..24b5a77 100644
--- a/fs/freevxfs/vxfs_immed.c
+++ b/fs/freevxfs/vxfs_immed.c
@@ -48,7 +48,7 @@
  * Unliked all other operations we do not go through the pagecache,
  * but do all work directly on the inode.
  */
-struct inode_operations vxfs_immed_symlink_iops = {
+const struct inode_operations vxfs_immed_symlink_iops = {
 	.readlink =		generic_readlink,
 	.follow_link =		vxfs_immed_follow_link,
 };
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 0b7ae89..098a915 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -44,7 +44,7 @@
 extern const struct address_space_operations vxfs_aops;
 extern const struct address_space_operations vxfs_immed_aops;
 
-extern struct inode_operations vxfs_immed_symlink_iops;
+extern const struct inode_operations vxfs_immed_symlink_iops;
 
 struct kmem_cache		*vxfs_inode_cachep;
 
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 3995d7f..bf86e54 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -52,7 +52,7 @@
 static struct dentry *	vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
 static int		vxfs_readdir(struct file *, void *, filldir_t);
 
-struct inode_operations vxfs_dir_inode_ops = {
+const struct inode_operations vxfs_dir_inode_ops = {
 	.lookup =		vxfs_lookup,
 };
 
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index ac28b08..647d600 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -59,7 +59,7 @@
 static int		vxfs_statfs(struct dentry *, struct kstatfs *);
 static int		vxfs_remount(struct super_block *, int *, char *);
 
-static struct super_operations vxfs_super_ops = {
+static const struct super_operations vxfs_super_ops = {
 	.read_inode =		vxfs_read_inode,
 	.clear_inode =		vxfs_clear_inode,
 	.put_super =		vxfs_put_super,
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 1794305..105d4a2 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -73,7 +73,7 @@
 					  struct fuse_conn *fc,
 					  const char *name,
 					  int mode, int nlink,
-					  struct inode_operations *iop,
+					  const struct inode_operations *iop,
 					  const struct file_operations *fop)
 {
 	struct dentry *dentry;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 4008047..406bf61 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1242,7 +1242,7 @@
 	return err;
 }
 
-static struct inode_operations fuse_dir_inode_operations = {
+static const struct inode_operations fuse_dir_inode_operations = {
 	.lookup		= fuse_lookup,
 	.mkdir		= fuse_mkdir,
 	.symlink	= fuse_symlink,
@@ -1270,7 +1270,7 @@
 	.fsync		= fuse_dir_fsync,
 };
 
-static struct inode_operations fuse_common_inode_operations = {
+static const struct inode_operations fuse_common_inode_operations = {
 	.setattr	= fuse_setattr,
 	.permission	= fuse_permission,
 	.getattr	= fuse_getattr,
@@ -1280,7 +1280,7 @@
 	.removexattr	= fuse_removexattr,
 };
 
-static struct inode_operations fuse_symlink_inode_operations = {
+static const struct inode_operations fuse_symlink_inode_operations = {
 	.setattr	= fuse_setattr,
 	.follow_link	= fuse_follow_link,
 	.put_link	= fuse_put_link,
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 2202551..5ab8e50 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -446,7 +446,7 @@
 	return fuse_iget(sb, 1, 0, &attr);
 }
 
-static struct super_operations fuse_super_operations = {
+static const struct super_operations fuse_super_operations = {
 	.alloc_inode    = fuse_alloc_inode,
 	.destroy_inode  = fuse_destroy_inode,
 	.read_inode	= fuse_read_inode,
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
index 3799f19..1dd4215 100644
--- a/fs/gfs2/locking/dlm/plock.c
+++ b/fs/gfs2/locking/dlm/plock.c
@@ -264,7 +264,7 @@
 	return 0;
 }
 
-static struct file_operations dev_fops = {
+static const struct file_operations dev_fops = {
 	.read    = dev_read,
 	.write   = dev_write,
 	.poll    = dev_poll,
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index f40a848..60f47bf 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -1115,7 +1115,7 @@
 	return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er);
 }
 
-struct inode_operations gfs2_file_iops = {
+const struct inode_operations gfs2_file_iops = {
 	.permission = gfs2_permission,
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
@@ -1125,7 +1125,7 @@
 	.removexattr = gfs2_removexattr,
 };
 
-struct inode_operations gfs2_dev_iops = {
+const struct inode_operations gfs2_dev_iops = {
 	.permission = gfs2_permission,
 	.setattr = gfs2_setattr,
 	.getattr = gfs2_getattr,
@@ -1135,7 +1135,7 @@
 	.removexattr = gfs2_removexattr,
 };
 
-struct inode_operations gfs2_dir_iops = {
+const struct inode_operations gfs2_dir_iops = {
 	.create = gfs2_create,
 	.lookup = gfs2_lookup,
 	.link = gfs2_link,
@@ -1154,7 +1154,7 @@
 	.removexattr = gfs2_removexattr,
 };
 
-struct inode_operations gfs2_symlink_iops = {
+const struct inode_operations gfs2_symlink_iops = {
 	.readlink = gfs2_readlink,
 	.follow_link = gfs2_follow_link,
 	.permission = gfs2_permission,
diff --git a/fs/gfs2/ops_inode.h b/fs/gfs2/ops_inode.h
index b15acb4..34f0caa 100644
--- a/fs/gfs2/ops_inode.h
+++ b/fs/gfs2/ops_inode.h
@@ -12,9 +12,9 @@
 
 #include <linux/fs.h>
 
-extern struct inode_operations gfs2_file_iops;
-extern struct inode_operations gfs2_dir_iops;
-extern struct inode_operations gfs2_symlink_iops;
-extern struct inode_operations gfs2_dev_iops;
+extern const struct inode_operations gfs2_file_iops;
+extern const struct inode_operations gfs2_dir_iops;
+extern const struct inode_operations gfs2_symlink_iops;
+extern const struct inode_operations gfs2_dev_iops;
 
 #endif /* __OPS_INODE_DOT_H__ */
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 47369d0..b89999d3 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -468,7 +468,7 @@
 	kmem_cache_free(gfs2_inode_cachep, inode);
 }
 
-struct super_operations gfs2_super_ops = {
+const struct super_operations gfs2_super_ops = {
 	.alloc_inode		= gfs2_alloc_inode,
 	.destroy_inode		= gfs2_destroy_inode,
 	.write_inode		= gfs2_write_inode,
diff --git a/fs/gfs2/ops_super.h b/fs/gfs2/ops_super.h
index 9de73f0..442a274 100644
--- a/fs/gfs2/ops_super.h
+++ b/fs/gfs2/ops_super.h
@@ -12,6 +12,6 @@
 
 #include <linux/fs.h>
 
-extern struct super_operations gfs2_super_ops;
+extern const struct super_operations gfs2_super_ops;
 
 #endif /* __OPS_SUPER_DOT_H__ */
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index e2e0358..7c69b98 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -320,7 +320,7 @@
 	.release	= hfs_dir_release,
 };
 
-struct inode_operations hfs_dir_inode_operations = {
+const struct inode_operations hfs_dir_inode_operations = {
 	.create		= hfs_create,
 	.lookup		= hfs_lookup,
 	.unlink		= hfs_unlink,
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 735332d..147374b 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -170,7 +170,7 @@
 
 /* dir.c */
 extern const struct file_operations hfs_dir_operations;
-extern struct inode_operations hfs_dir_inode_operations;
+extern const struct inode_operations hfs_dir_inode_operations;
 
 /* extent.c */
 extern int hfs_ext_keycmp(const btree_key *, const btree_key *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 5cb7f8f..fafcba5 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -18,7 +18,7 @@
 #include "btree.h"
 
 static const struct file_operations hfs_file_operations;
-static struct inode_operations hfs_file_inode_operations;
+static const struct inode_operations hfs_file_inode_operations;
 
 /*================ Variable-like macros ================*/
 
@@ -612,7 +612,7 @@
 	.release	= hfs_file_release,
 };
 
-static struct inode_operations hfs_file_inode_operations = {
+static const struct inode_operations hfs_file_inode_operations = {
 	.lookup		= hfs_file_lookup,
 	.truncate	= hfs_file_truncate,
 	.setattr	= hfs_inode_setattr,
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index a369879..623f509 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -154,7 +154,7 @@
 	kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
 }
 
-static struct super_operations hfs_super_operations = {
+static const struct super_operations hfs_super_operations = {
 	.alloc_inode	= hfs_alloc_inode,
 	.destroy_inode	= hfs_destroy_inode,
 	.write_inode	= hfs_write_inode,
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index e886ac8..7813700 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -471,7 +471,7 @@
 	return res;
 }
 
-struct inode_operations hfsplus_dir_inode_operations = {
+const struct inode_operations hfsplus_dir_inode_operations = {
 	.lookup		= hfsplus_lookup,
 	.create		= hfsplus_create,
 	.link		= hfsplus_link,
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 75e8c4d..642012a 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -268,10 +268,10 @@
 	return 0;
 }
 
-extern struct inode_operations hfsplus_dir_inode_operations;
+extern const struct inode_operations hfsplus_dir_inode_operations;
 extern struct file_operations hfsplus_dir_operations;
 
-static struct inode_operations hfsplus_file_inode_operations = {
+static const struct inode_operations hfsplus_file_inode_operations = {
 	.lookup		= hfsplus_file_lookup,
 	.truncate	= hfsplus_file_truncate,
 	.permission	= hfsplus_permission,
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 0f513c6..5a282f6 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -260,7 +260,7 @@
 	return 0;
 }
 
-static struct super_operations hfsplus_sops = {
+static const struct super_operations hfsplus_sops = {
 	.alloc_inode	= hfsplus_alloc_inode,
 	.destroy_inode	= hfsplus_destroy_inode,
 	.read_inode	= hfsplus_read_inode,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 69a376f..e965eb1 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -52,8 +52,8 @@
 
 #define HOSTFS_SUPER_MAGIC 0x00c0ffee
 
-static struct inode_operations hostfs_iops;
-static struct inode_operations hostfs_dir_iops;
+static const struct inode_operations hostfs_iops;
+static const struct inode_operations hostfs_dir_iops;
 static const struct address_space_operations hostfs_link_aops;
 
 #ifndef MODULE
@@ -309,7 +309,7 @@
 	read_inode(inode);
 }
 
-static struct super_operations hostfs_sbops = {
+static const struct super_operations hostfs_sbops = {
 	.alloc_inode	= hostfs_alloc_inode,
 	.drop_inode	= generic_delete_inode,
 	.delete_inode   = hostfs_delete_inode,
@@ -880,7 +880,7 @@
 	return(0);
 }
 
-static struct inode_operations hostfs_iops = {
+static const struct inode_operations hostfs_iops = {
 	.create		= hostfs_create,
 	.link		= hostfs_link,
 	.unlink		= hostfs_unlink,
@@ -894,7 +894,7 @@
 	.getattr	= hostfs_getattr,
 };
 
-static struct inode_operations hostfs_dir_iops = {
+static const struct inode_operations hostfs_dir_iops = {
 	.create		= hostfs_create,
 	.lookup		= hostfs_lookup,
 	.link		= hostfs_link,
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index fb4c891..b4eafc0 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -132,7 +132,7 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations hpfs_file_iops =
+const struct inode_operations hpfs_file_iops =
 {
 	.truncate	= hpfs_truncate,
 	.setattr	= hpfs_notify_change,
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 1c07aa8..42ff60c 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -266,7 +266,7 @@
 
 int hpfs_file_fsync(struct file *, struct dentry *, int);
 extern const struct file_operations hpfs_file_ops;
-extern struct inode_operations hpfs_file_iops;
+extern const struct inode_operations hpfs_file_iops;
 extern const struct address_space_operations hpfs_aops;
 
 /* inode.c */
@@ -302,7 +302,7 @@
 
 /* namei.c */
 
-extern struct inode_operations hpfs_dir_iops;
+extern const struct inode_operations hpfs_dir_iops;
 extern const struct address_space_operations hpfs_symlink_aops;
 
 static inline struct hpfs_inode_info *hpfs_i(struct inode *inode)
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 2507e73..9953cf9 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -659,7 +659,7 @@
 	return err;
 }
 
-struct inode_operations hpfs_dir_iops =
+const struct inode_operations hpfs_dir_iops =
 {
 	.create		= hpfs_create,
 	.lookup		= hpfs_lookup,
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index d4abc1a..e0174e3 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -426,7 +426,7 @@
 
 /* Super operations */
 
-static struct super_operations hpfs_sops =
+static const struct super_operations hpfs_sops =
 {
 	.alloc_inode	= hpfs_alloc_inode,
 	.destroy_inode	= hpfs_destroy_inode,
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index afd340a..affb741 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -43,7 +43,7 @@
 
 #define HPPFS_SUPER_MAGIC 0xb00000ee
 
-static struct super_operations hppfs_sbops;
+static const struct super_operations hppfs_sbops;
 
 static int is_pid(struct dentry *dentry)
 {
@@ -212,7 +212,7 @@
 	return(ERR_PTR(err));
 }
 
-static struct inode_operations hppfs_file_iops = {
+static const struct inode_operations hppfs_file_iops = {
 };
 
 static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count,
@@ -649,7 +649,7 @@
 	kfree(HPPFS_I(inode));
 }
 
-static struct super_operations hppfs_sbops = {
+static const struct super_operations hppfs_sbops = {
 	.alloc_inode	= hppfs_alloc_inode,
 	.destroy_inode	= hppfs_destroy_inode,
 	.read_inode	= hppfs_read_inode,
@@ -693,11 +693,11 @@
 	return ret;
 }
 
-static struct inode_operations hppfs_dir_iops = {
+static const struct inode_operations hppfs_dir_iops = {
 	.lookup		= hppfs_lookup,
 };
 
-static struct inode_operations hppfs_link_iops = {
+static const struct inode_operations hppfs_link_iops = {
 	.readlink	= hppfs_readlink,
 	.follow_link	= hppfs_follow_link,
 };
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index e6bd553..8c718a3 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -33,11 +33,11 @@
 /* some random number */
 #define HUGETLBFS_MAGIC	0x958458f6
 
-static struct super_operations hugetlbfs_ops;
+static const struct super_operations hugetlbfs_ops;
 static const struct address_space_operations hugetlbfs_aops;
 const struct file_operations hugetlbfs_file_operations;
-static struct inode_operations hugetlbfs_dir_inode_operations;
-static struct inode_operations hugetlbfs_inode_operations;
+static const struct inode_operations hugetlbfs_dir_inode_operations;
+static const struct inode_operations hugetlbfs_inode_operations;
 
 static struct backing_dev_info hugetlbfs_backing_dev_info = {
 	.ra_pages	= 0,	/* No readahead */
@@ -563,7 +563,7 @@
 	.get_unmapped_area	= hugetlb_get_unmapped_area,
 };
 
-static struct inode_operations hugetlbfs_dir_inode_operations = {
+static const struct inode_operations hugetlbfs_dir_inode_operations = {
 	.create		= hugetlbfs_create,
 	.lookup		= simple_lookup,
 	.link		= simple_link,
@@ -576,11 +576,11 @@
 	.setattr	= hugetlbfs_setattr,
 };
 
-static struct inode_operations hugetlbfs_inode_operations = {
+static const struct inode_operations hugetlbfs_inode_operations = {
 	.setattr	= hugetlbfs_setattr,
 };
 
-static struct super_operations hugetlbfs_ops = {
+static const struct super_operations hugetlbfs_ops = {
 	.alloc_inode    = hugetlbfs_alloc_inode,
 	.destroy_inode  = hugetlbfs_destroy_inode,
 	.statfs		= hugetlbfs_statfs,
diff --git a/fs/inode.c b/fs/inode.c
index e6d9307..5abb097 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1000,7 +1000,7 @@
  */
 void generic_delete_inode(struct inode *inode)
 {
-	struct super_operations *op = inode->i_sb->s_op;
+	const struct super_operations *op = inode->i_sb->s_op;
 
 	list_del_init(&inode->i_list);
 	list_del_init(&inode->i_sb_list);
@@ -1093,7 +1093,7 @@
  */
 static inline void iput_final(struct inode *inode)
 {
-	struct super_operations *op = inode->i_sb->s_op;
+	const struct super_operations *op = inode->i_sb->s_op;
 	void (*drop)(struct inode *) = generic_drop_inode;
 
 	if (op && op->drop_inode)
@@ -1113,7 +1113,7 @@
 void iput(struct inode *inode)
 {
 	if (inode) {
-		struct super_operations *op = inode->i_sb->s_op;
+		const struct super_operations *op = inode->i_sb->s_op;
 
 		BUG_ON(inode->i_state == I_CLEAR);
 
@@ -1251,33 +1251,6 @@
 
 EXPORT_SYMBOL(inode_needs_sync);
 
-/*
- *	Quota functions that want to walk the inode lists..
- */
-#ifdef CONFIG_QUOTA
-
-void remove_dquot_ref(struct super_block *sb, int type,
-			struct list_head *tofree_head)
-{
-	struct inode *inode;
-
-	if (!sb->dq_op)
-		return;	/* nothing to do */
-	spin_lock(&inode_lock);	/* This lock is for inodes code */
-
-	/*
-	 * We don't have to lock against quota code - test IS_QUOTAINIT is
-	 * just for speedup...
-	 */
-	list_for_each_entry(inode, &sb->s_inodes, i_sb_list)
-		if (!IS_NOQUOTA(inode))
-			remove_inode_dquot_ref(inode, type, tofree_head);
-
-	spin_unlock(&inode_lock);
-}
-
-#endif
-
 int inode_wait(void *word)
 {
 	schedule();
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 55f6da5..9f2224f 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -455,8 +455,16 @@
 			break;
 
 		kevent = inotify_dev_get_event(dev);
-		if (event_size + kevent->event.len > count)
+		if (event_size + kevent->event.len > count) {
+			if (ret == 0 && count > 0) {
+				/*
+				 * could not get a single event because we
+				 * didn't have enough buffer space.
+				 */
+				ret = -EINVAL;
+			}
 			break;
+		}
 
 		if (copy_to_user(buf, &kevent->event, event_size)) {
 			ret = -EFAULT;
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 89e8da1..10d2c21 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -60,6 +60,7 @@
 	int data = IOPRIO_PRIO_DATA(ioprio);
 	struct task_struct *p, *g;
 	struct user_struct *user;
+	struct pid *pgrp;
 	int ret;
 
 	switch (class) {
@@ -98,12 +99,14 @@
 			break;
 		case IOPRIO_WHO_PGRP:
 			if (!who)
-				who = process_group(current);
-			do_each_task_pid(who, PIDTYPE_PGID, p) {
+				pgrp = task_pgrp(current);
+			else
+				pgrp = find_pid(who);
+			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 				ret = set_task_ioprio(p, ioprio);
 				if (ret)
 					break;
-			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case IOPRIO_WHO_USER:
 			if (!who)
@@ -167,6 +170,7 @@
 {
 	struct task_struct *g, *p;
 	struct user_struct *user;
+	struct pid *pgrp;
 	int ret = -ESRCH;
 	int tmpio;
 
@@ -182,8 +186,10 @@
 			break;
 		case IOPRIO_WHO_PGRP:
 			if (!who)
-				who = process_group(current);
-			do_each_task_pid(who, PIDTYPE_PGID, p) {
+				pgrp = task_pgrp(current);
+			else
+				pgrp = find_pid(who);
+			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 				tmpio = get_task_ioprio(p);
 				if (tmpio < 0)
 					continue;
@@ -191,7 +197,7 @@
 					ret = tmpio;
 				else
 					ret = ioprio_best(ret, tmpio);
-			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case IOPRIO_WHO_USER:
 			if (!who)
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 4af2548..0e94c31 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -24,7 +24,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations isofs_dir_inode_operations =
+const struct inode_operations isofs_dir_inode_operations =
 {
 	.lookup		= isofs_lookup,
 };
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index ea55b6c..64a96cd 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -106,7 +106,7 @@
 	return 0;
 }
 
-static struct super_operations isofs_sops = {
+static const struct super_operations isofs_sops = {
 	.alloc_inode	= isofs_alloc_inode,
 	.destroy_inode	= isofs_destroy_inode,
 	.read_inode	= isofs_read_inode,
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index e6308c8..efe2872 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -174,7 +174,7 @@
 	}
 }
 
-extern struct inode_operations isofs_dir_inode_operations;
+extern const struct inode_operations isofs_dir_inode_operations;
 extern const struct file_operations isofs_dir_operations;
 extern const struct address_space_operations isofs_symlink_aops;
 extern struct export_operations isofs_export_ops;
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 6ee2066..9602b92 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -54,11 +54,11 @@
 
 static int jffs_remove(struct inode *dir, struct dentry *dentry, int type);
 
-static struct super_operations jffs_ops;
+static const struct super_operations jffs_ops;
 static const struct file_operations jffs_file_operations;
-static struct inode_operations jffs_file_inode_operations;
+static const struct inode_operations jffs_file_inode_operations;
 static const struct file_operations jffs_dir_operations;
-static struct inode_operations jffs_dir_inode_operations;
+static const struct inode_operations jffs_dir_inode_operations;
 static const struct address_space_operations jffs_address_operations;
 
 struct kmem_cache     *node_cache = NULL;
@@ -1642,7 +1642,7 @@
 };
 
 
-static struct inode_operations jffs_file_inode_operations =
+static const struct inode_operations jffs_file_inode_operations =
 {
 	.lookup		= jffs_lookup,          /* lookup */
 	.setattr	= jffs_setattr,
@@ -1655,7 +1655,7 @@
 };
 
 
-static struct inode_operations jffs_dir_inode_operations =
+static const struct inode_operations jffs_dir_inode_operations =
 {
 	.create		= jffs_create,
 	.lookup		= jffs_lookup,
@@ -1774,7 +1774,7 @@
 	return 0;
 }
 
-static struct super_operations jffs_ops =
+static const struct super_operations jffs_ops =
 {
 	.read_inode	= jffs_read_inode,
 	.delete_inode 	= jffs_delete_inode,
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index da6034d..cdbe2fe 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -46,7 +46,7 @@
 };
 
 
-struct inode_operations jffs2_dir_inode_operations =
+const struct inode_operations jffs2_dir_inode_operations =
 {
 	.create =	jffs2_create,
 	.lookup =	jffs2_lookup,
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 242875f..e82eeaf 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -54,7 +54,7 @@
 
 /* jffs2_file_inode_operations */
 
-struct inode_operations jffs2_file_inode_operations =
+const struct inode_operations jffs2_file_inode_operations =
 {
 	.permission =	jffs2_permission,
 	.setattr =	jffs2_setattr,
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 9f41fc0..e07a0ed 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -153,11 +153,11 @@
 
 /* dir.c */
 extern const struct file_operations jffs2_dir_operations;
-extern struct inode_operations jffs2_dir_inode_operations;
+extern const struct inode_operations jffs2_dir_inode_operations;
 
 /* file.c */
 extern const struct file_operations jffs2_file_operations;
-extern struct inode_operations jffs2_file_inode_operations;
+extern const struct inode_operations jffs2_file_inode_operations;
 extern const struct address_space_operations jffs2_file_address_operations;
 int jffs2_fsync(struct file *, struct dentry *, int);
 int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
@@ -166,7 +166,7 @@
 int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 
 /* symlink.c */
-extern struct inode_operations jffs2_symlink_inode_operations;
+extern const struct inode_operations jffs2_symlink_inode_operations;
 
 /* fs.c */
 int jffs2_setattr (struct dentry *, struct iattr *);
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 08a0e6c..cc7e8e7 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -66,7 +66,7 @@
 	return 0;
 }
 
-static struct super_operations jffs2_super_operations =
+static const struct super_operations jffs2_super_operations =
 {
 	.alloc_inode =	jffs2_alloc_inode,
 	.destroy_inode =jffs2_destroy_inode,
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index b90d5aa..7e4882c 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -20,7 +20,7 @@
 
 static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd);
 
-struct inode_operations jffs2_symlink_inode_operations =
+const struct inode_operations jffs2_symlink_inode_operations =
 {
 	.readlink =	generic_readlink,
 	.follow_link =	jffs2_follow_link,
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index aa9132d..f7f8eff 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -88,7 +88,7 @@
 	return 0;
 }
 
-struct inode_operations jfs_file_inode_operations = {
+const struct inode_operations jfs_file_inode_operations = {
 	.truncate	= jfs_truncate,
 	.setxattr	= jfs_setxattr,
 	.getxattr	= jfs_getxattr,
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 0d06ccf..6802837 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -35,10 +35,10 @@
 extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern const struct address_space_operations jfs_aops;
-extern struct inode_operations jfs_dir_inode_operations;
+extern const struct inode_operations jfs_dir_inode_operations;
 extern const struct file_operations jfs_dir_operations;
-extern struct inode_operations jfs_file_inode_operations;
+extern const struct inode_operations jfs_file_inode_operations;
 extern const struct file_operations jfs_file_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
+extern const struct inode_operations jfs_symlink_inode_operations;
 extern struct dentry_operations jfs_ci_dentry_operations;
 #endif				/* _H_JFS_INODE */
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 7ab4756..41c2047 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1503,7 +1503,7 @@
 	return parent;
 }
 
-struct inode_operations jfs_dir_inode_operations = {
+const struct inode_operations jfs_dir_inode_operations = {
 	.create		= jfs_create,
 	.lookup		= jfs_lookup,
 	.link		= jfs_link,
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 846ac8f..52d73d5 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -46,7 +46,7 @@
 
 static struct kmem_cache * jfs_inode_cachep;
 
-static struct super_operations jfs_super_operations;
+static const struct super_operations jfs_super_operations;
 static struct export_operations jfs_export_operations;
 static struct file_system_type jfs_fs_type;
 
@@ -716,7 +716,7 @@
 
 #endif
 
-static struct super_operations jfs_super_operations = {
+static const struct super_operations jfs_super_operations = {
 	.alloc_inode	= jfs_alloc_inode,
 	.destroy_inode	= jfs_destroy_inode,
 	.read_inode	= jfs_read_inode,
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index cee43f3..4af1a05 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -29,7 +29,7 @@
 	return NULL;
 }
 
-struct inode_operations jfs_symlink_inode_operations = {
+const struct inode_operations jfs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= jfs_follow_link,
 	.setxattr	= jfs_setxattr,
diff --git a/fs/libfs.c b/fs/libfs.c
index 503898d..7d48704 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -186,7 +186,7 @@
 	.fsync		= simple_sync_file,
 };
 
-struct inode_operations simple_dir_inode_operations = {
+const struct inode_operations simple_dir_inode_operations = {
 	.lookup		= simple_lookup,
 };
 
@@ -195,11 +195,11 @@
  * will never be mountable)
  */
 int get_sb_pseudo(struct file_system_type *fs_type, char *name,
-	struct super_operations *ops, unsigned long magic,
+	const struct super_operations *ops, unsigned long magic,
 	struct vfsmount *mnt)
 {
 	struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
-	static struct super_operations default_ops = {.statfs = simple_statfs};
+	static const struct super_operations default_ops = {.statfs = simple_statfs};
 	struct dentry *dentry;
 	struct inode *root;
 	struct qstr d_name = {.name = name, .len = strlen(name)};
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 3d4610c..22d4032 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -192,7 +192,7 @@
 nlmsvc_lookup_host(struct svc_rqst *rqstp,
 			const char *hostname, int hostname_len)
 {
-	return nlm_lookup_host(1, &rqstp->rq_addr,
+	return nlm_lookup_host(1, svc_addr_in(rqstp),
 			       rqstp->rq_prot, rqstp->rq_vers,
 			       hostname, hostname_len);
 }
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 8ca1808..80fcacc 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -141,6 +141,7 @@
 	 */
 	while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) {
 		long timeout = MAX_SCHEDULE_TIMEOUT;
+		char buf[RPC_MAX_ADDRBUFLEN];
 
 		if (signalled()) {
 			flush_signals(current);
@@ -175,11 +176,10 @@
 			break;
 		}
 
-		dprintk("lockd: request from %08x\n",
-			(unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
+		dprintk("lockd: request from %s\n",
+				svc_print_addr(rqstp, buf, sizeof(buf)));
 
 		svc_process(rqstp);
-
 	}
 
 	flush_signals(current);
@@ -223,23 +223,29 @@
 	return found;
 }
 
+/*
+ * Make any sockets that are needed but not present.
+ * If nlm_udpport or nlm_tcpport were set as module
+ * options, make those sockets unconditionally
+ */
 static int make_socks(struct svc_serv *serv, int proto)
 {
-	/* Make any sockets that are needed but not present.
-	 * If nlm_udpport or nlm_tcpport were set as module
-	 * options, make those sockets unconditionally
-	 */
-	static int		warned;
+	static int warned;
 	int err = 0;
+
 	if (proto == IPPROTO_UDP || nlm_udpport)
 		if (!find_socket(serv, IPPROTO_UDP))
-			err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport);
-	if (err == 0 && (proto == IPPROTO_TCP || nlm_tcpport))
+			err = svc_makesock(serv, IPPROTO_UDP, nlm_udpport,
+						SVC_SOCK_DEFAULTS);
+	if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport))
 		if (!find_socket(serv, IPPROTO_TCP))
-			err= svc_makesock(serv, IPPROTO_TCP, nlm_tcpport);
-	if (!err)
+			err = svc_makesock(serv, IPPROTO_TCP, nlm_tcpport,
+						SVC_SOCK_DEFAULTS);
+
+	if (err >= 0) {
 		warned = 0;
-	else if (warned++ == 0)
+		err = 0;
+	} else if (warned++ == 0)
 		printk(KERN_WARNING
 		       "lockd_up: makesock failed, error=%d\n", err);
 	return err;
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index f67146a..47a66aa 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -224,7 +224,7 @@
 	resp->cookie = argp->cookie;
 
 	dprintk("lockd: GRANTED       called\n");
-	resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+	resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
 	dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
 	return rpc_success;
 }
@@ -421,15 +421,16 @@
 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in	saddr;
+
+	memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
 
 	dprintk("lockd: SM_NOTIFY     called\n");
 	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
 	 || ntohs(saddr.sin_port) >= 1024) {
-		printk(KERN_WARNING
-			"lockd: rejected NSM callback from %08x:%d\n",
-			ntohl(rqstp->rq_addr.sin_addr.s_addr),
-			ntohs(rqstp->rq_addr.sin_port));
+		char buf[RPC_MAX_ADDRBUFLEN];
+		printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
+				svc_print_addr(rqstp, buf, sizeof(buf)));
 		return rpc_system_err;
 	}
 
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 3707c3a..31cb484 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -253,7 +253,7 @@
 	resp->cookie = argp->cookie;
 
 	dprintk("lockd: GRANTED       called\n");
-	resp->status = nlmclnt_grant(&rqstp->rq_addr, &argp->lock);
+	resp->status = nlmclnt_grant(svc_addr_in(rqstp), &argp->lock);
 	dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
 	return rpc_success;
 }
@@ -452,15 +452,16 @@
 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
 					      void	        *resp)
 {
-	struct sockaddr_in	saddr = rqstp->rq_addr;
+	struct sockaddr_in	saddr;
+
+	memcpy(&saddr, svc_addr_in(rqstp), sizeof(saddr));
 
 	dprintk("lockd: SM_NOTIFY     called\n");
 	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
 	 || ntohs(saddr.sin_port) >= 1024) {
-		printk(KERN_WARNING
-			"lockd: rejected NSM callback from %08x:%d\n",
-			ntohl(rqstp->rq_addr.sin_addr.s_addr),
-			ntohs(rqstp->rq_addr.sin_port));
+		char buf[RPC_MAX_ADDRBUFLEN];
+		printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
+				svc_print_addr(rqstp, buf, sizeof(buf)));
 		return rpc_system_err;
 	}
 
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c
index df6b107..c4a554d 100644
--- a/fs/minix/bitmap.c
+++ b/fs/minix/bitmap.c
@@ -26,14 +26,14 @@
 	for (i=0; i<numblocks-1; i++) {
 		if (!(bh=map[i])) 
 			return(0);
-		for (j=0; j<BLOCK_SIZE; j++)
+		for (j=0; j<bh->b_size; j++)
 			sum += nibblemap[bh->b_data[j] & 0xf]
 				+ nibblemap[(bh->b_data[j]>>4) & 0xf];
 	}
 
 	if (numblocks==0 || !(bh=map[numblocks-1]))
 		return(0);
-	i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2;
+	i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
 	for (j=0; j<i; j++) {
 		sum += nibblemap[bh->b_data[j] & 0xf]
 			+ nibblemap[(bh->b_data[j]>>4) & 0xf];
@@ -48,28 +48,29 @@
 	return(sum);
 }
 
-void minix_free_block(struct inode * inode, int block)
+void minix_free_block(struct inode *inode, unsigned long block)
 {
-	struct super_block * sb = inode->i_sb;
-	struct minix_sb_info * sbi = minix_sb(sb);
-	struct buffer_head * bh;
-	unsigned int bit,zone;
+	struct super_block *sb = inode->i_sb;
+	struct minix_sb_info *sbi = minix_sb(sb);
+	struct buffer_head *bh;
+	int k = sb->s_blocksize_bits + 3;
+	unsigned long bit, zone;
 
 	if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
 		printk("Trying to free block not in datazone\n");
 		return;
 	}
 	zone = block - sbi->s_firstdatazone + 1;
-	bit = zone & 8191;
-	zone >>= 13;
+	bit = zone & ((1<<k) - 1);
+	zone >>= k;
 	if (zone >= sbi->s_zmap_blocks) {
 		printk("minix_free_block: nonexistent bitmap buffer\n");
 		return;
 	}
 	bh = sbi->s_zmap[zone];
 	lock_kernel();
-	if (!minix_test_and_clear_bit(bit,bh->b_data))
-		printk("free_block (%s:%d): bit already cleared\n",
+	if (!minix_test_and_clear_bit(bit, bh->b_data))
+		printk("minix_free_block (%s:%lu): bit already cleared\n",
 		       sb->s_id, block);
 	unlock_kernel();
 	mark_buffer_dirty(bh);
@@ -79,6 +80,7 @@
 int minix_new_block(struct inode * inode)
 {
 	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
+	int bits_per_zone = 8 * inode->i_sb->s_blocksize;
 	int i;
 
 	for (i = 0; i < sbi->s_zmap_blocks; i++) {
@@ -86,11 +88,12 @@
 		int j;
 
 		lock_kernel();
-		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) {
-			minix_set_bit(j,bh->b_data);
+		j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
+		if (j < bits_per_zone) {
+			minix_set_bit(j, bh->b_data);
 			unlock_kernel();
 			mark_buffer_dirty(bh);
-			j += i*8192 + sbi->s_firstdatazone-1;
+			j += i * bits_per_zone + sbi->s_firstdatazone-1;
 			if (j < sbi->s_firstdatazone || j >= sbi->s_nzones)
 				break;
 			return j;
@@ -137,6 +140,7 @@
 	int block;
 	struct minix_sb_info *sbi = minix_sb(sb);
 	struct minix2_inode *p;
+	int minix2_inodes_per_block = sb->s_blocksize / sizeof(struct minix2_inode);
 
 	*bh = NULL;
 	if (!ino || ino > sbi->s_ninodes) {
@@ -146,14 +150,14 @@
 	}
 	ino--;
 	block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
-		 ino / MINIX2_INODES_PER_BLOCK;
+		 ino / minix2_inodes_per_block;
 	*bh = sb_bread(sb, block);
 	if (!*bh) {
 		printk("Unable to read inode block\n");
 		return NULL;
 	}
 	p = (void *)(*bh)->b_data;
-	return p + ino % MINIX2_INODES_PER_BLOCK;
+	return p + ino % minix2_inodes_per_block;
 }
 
 /* Clear the link count and mode of a deleted inode on disk. */
@@ -185,26 +189,30 @@
 
 void minix_free_inode(struct inode * inode)
 {
+	struct super_block *sb = inode->i_sb;
 	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
-	struct buffer_head * bh;
-	unsigned long ino;
+	struct buffer_head *bh;
+	int k = sb->s_blocksize_bits + 3;
+	unsigned long ino, bit;
 
 	ino = inode->i_ino;
 	if (ino < 1 || ino > sbi->s_ninodes) {
 		printk("minix_free_inode: inode 0 or nonexistent inode\n");
 		goto out;
 	}
-	if ((ino >> 13) >= sbi->s_imap_blocks) {
+	bit = ino & ((1<<k) - 1);
+	ino >>= k;
+	if (ino >= sbi->s_imap_blocks) {
 		printk("minix_free_inode: nonexistent imap in superblock\n");
 		goto out;
 	}
 
 	minix_clear_inode(inode);	/* clear on-disk copy */
 
-	bh = sbi->s_imap[ino >> 13];
+	bh = sbi->s_imap[ino];
 	lock_kernel();
-	if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
-		printk("minix_free_inode: bit %lu already cleared\n", ino);
+	if (!minix_test_and_clear_bit(bit, bh->b_data))
+		printk("minix_free_inode: bit %lu already cleared\n", bit);
 	unlock_kernel();
 	mark_buffer_dirty(bh);
  out:
@@ -217,35 +225,38 @@
 	struct minix_sb_info *sbi = minix_sb(sb);
 	struct inode *inode = new_inode(sb);
 	struct buffer_head * bh;
-	int i,j;
+	int bits_per_zone = 8 * sb->s_blocksize;
+	unsigned long j;
+	int i;
 
 	if (!inode) {
 		*error = -ENOMEM;
 		return NULL;
 	}
-	j = 8192;
+	j = bits_per_zone;
 	bh = NULL;
 	*error = -ENOSPC;
 	lock_kernel();
 	for (i = 0; i < sbi->s_imap_blocks; i++) {
 		bh = sbi->s_imap[i];
-		if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
+		j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
+		if (j < bits_per_zone)
 			break;
 	}
-	if (!bh || j >= 8192) {
+	if (!bh || j >= bits_per_zone) {
 		unlock_kernel();
 		iput(inode);
 		return NULL;
 	}
-	if (minix_test_and_set_bit(j,bh->b_data)) {	/* shouldn't happen */
-		printk("new_inode: bit already set\n");
+	if (minix_test_and_set_bit(j, bh->b_data)) {	/* shouldn't happen */
 		unlock_kernel();
+		printk("minix_new_inode: bit already set\n");
 		iput(inode);
 		return NULL;
 	}
 	unlock_kernel();
 	mark_buffer_dirty(bh);
-	j += i*8192;
+	j += i * bits_per_zone;
 	if (!j || j > sbi->s_ninodes) {
 		iput(inode);
 		return NULL;
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index ab782c4..cb4cb57 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -4,6 +4,8 @@
  *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  minix directory handling functions
+ *
+ *  Updated to filesystem version 3 by Daniel Aragones
  */
 
 #include "minix.h"
@@ -11,6 +13,7 @@
 #include <linux/smp_lock.h>
 
 typedef struct minix_dir_entry minix_dirent;
+typedef struct minix3_dir_entry minix3_dirent;
 
 static int minix_readdir(struct file *, void *, filldir_t);
 
@@ -89,6 +92,8 @@
 	unsigned long npages = dir_pages(inode);
 	struct minix_sb_info *sbi = minix_sb(sb);
 	unsigned chunk_size = sbi->s_dirsize;
+	char *name;
+	__u32 inumber;
 
 	lock_kernel();
 
@@ -105,16 +110,24 @@
 		kaddr = (char *)page_address(page);
 		p = kaddr+offset;
 		limit = kaddr + minix_last_byte(inode, n) - chunk_size;
-		for ( ; p <= limit ; p = minix_next_entry(p, sbi)) {
-			minix_dirent *de = (minix_dirent *)p;
-			if (de->inode) {
+		for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
+			if (sbi->s_version == MINIX_V3) {
+				minix3_dirent *de3 = (minix3_dirent *)p;
+				name = de3->name;
+				inumber = de3->inode;
+	 		} else {
+				minix_dirent *de = (minix_dirent *)p;
+				name = de->name;
+				inumber = de->inode;
+			}
+			if (inumber) {
 				int over;
-				unsigned l = strnlen(de->name,sbi->s_namelen);
 
+				unsigned l = strnlen(name, sbi->s_namelen);
 				offset = p - kaddr;
-				over = filldir(dirent, de->name, l,
-						(n<<PAGE_CACHE_SHIFT) | offset,
-						de->inode, DT_UNKNOWN);
+				over = filldir(dirent, name, l,
+					(n << PAGE_CACHE_SHIFT) | offset,
+					inumber, DT_UNKNOWN);
 				if (over) {
 					dir_put_page(page);
 					goto done;
@@ -156,23 +169,34 @@
 	unsigned long n;
 	unsigned long npages = dir_pages(dir);
 	struct page *page = NULL;
-	struct minix_dir_entry *de;
+	char *p;
 
+	char *namx;
+	__u32 inumber;
 	*res_page = NULL;
 
 	for (n = 0; n < npages; n++) {
-		char *kaddr;
+		char *kaddr, *limit;
+
 		page = dir_get_page(dir, n);
 		if (IS_ERR(page))
 			continue;
 
 		kaddr = (char*)page_address(page);
-		de = (struct minix_dir_entry *) kaddr;
-		kaddr += minix_last_byte(dir, n) - sbi->s_dirsize;
-		for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) {
-			if (!de->inode)
+		limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize;
+		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+			if (sbi->s_version == MINIX_V3) {
+				minix3_dirent *de3 = (minix3_dirent *)p;
+				namx = de3->name;
+				inumber = de3->inode;
+ 			} else {
+				minix_dirent *de = (minix_dirent *)p;
+				namx = de->name;
+				inumber = de->inode;
+			}
+			if (!inumber)
 				continue;
-			if (namecompare(namelen,sbi->s_namelen,name,de->name))
+			if (namecompare(namelen, sbi->s_namelen, name, namx))
 				goto found;
 		}
 		dir_put_page(page);
@@ -181,7 +205,7 @@
 
 found:
 	*res_page = page;
-	return de;
+	return (minix_dirent *)p;
 }
 
 int minix_add_link(struct dentry *dentry, struct inode *inode)
@@ -192,12 +216,15 @@
 	struct super_block * sb = dir->i_sb;
 	struct minix_sb_info * sbi = minix_sb(sb);
 	struct page *page = NULL;
-	struct minix_dir_entry * de;
 	unsigned long npages = dir_pages(dir);
 	unsigned long n;
-	char *kaddr;
+	char *kaddr, *p;
+	minix_dirent *de;
+	minix3_dirent *de3;
 	unsigned from, to;
 	int err;
+	char *namx = NULL;
+	__u32 inumber;
 
 	/*
 	 * We take care of directory expansion in the same loop
@@ -205,7 +232,7 @@
 	 * to protect that region.
 	 */
 	for (n = 0; n <= npages; n++) {
-		char *dir_end;
+		char *limit, *dir_end;
 
 		page = dir_get_page(dir, n);
 		err = PTR_ERR(page);
@@ -214,20 +241,30 @@
 		lock_page(page);
 		kaddr = (char*)page_address(page);
 		dir_end = kaddr + minix_last_byte(dir, n);
-		de = (minix_dirent *)kaddr;
-		kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
-		while ((char *)de <= kaddr) {
-			if ((char *)de == dir_end) {
+		limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize;
+		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+			de = (minix_dirent *)p;
+			de3 = (minix3_dirent *)p;
+			if (sbi->s_version == MINIX_V3) {
+				namx = de3->name;
+				inumber = de3->inode;
+		 	} else {
+  				namx = de->name;
+				inumber = de->inode;
+			}
+			if (p == dir_end) {
 				/* We hit i_size */
-				de->inode = 0;
+				if (sbi->s_version == MINIX_V3)
+					de3->inode = 0;
+		 		else
+					de->inode = 0;
 				goto got_it;
 			}
-			if (!de->inode)
+			if (!inumber)
 				goto got_it;
 			err = -EEXIST;
-			if (namecompare(namelen,sbi->s_namelen,name,de->name))
+			if (namecompare(namelen, sbi->s_namelen, name, namx))
 				goto out_unlock;
-			de = minix_next_entry(de, sbi);
 		}
 		unlock_page(page);
 		dir_put_page(page);
@@ -236,14 +273,19 @@
 	return -EINVAL;
 
 got_it:
-	from = (char*)de - (char*)page_address(page);
+	from = p - (char*)page_address(page);
 	to = from + sbi->s_dirsize;
 	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
 	if (err)
 		goto out_unlock;
-	memcpy (de->name, name, namelen);
-	memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2);
-	de->inode = inode->i_ino;
+	memcpy (namx, name, namelen);
+	if (sbi->s_version == MINIX_V3) {
+		memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4);
+		de3->inode = inode->i_ino;
+	} else {
+		memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
+		de->inode = inode->i_ino;
+	}
 	err = dir_commit_chunk(page, from, to);
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
 	mark_inode_dirty(dir);
@@ -283,8 +325,7 @@
 {
 	struct address_space *mapping = inode->i_mapping;
 	struct page *page = grab_cache_page(mapping, 0);
-	struct minix_sb_info * sbi = minix_sb(inode->i_sb);
-	struct minix_dir_entry * de;
+	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
 	char *kaddr;
 	int err;
 
@@ -299,12 +340,23 @@
 	kaddr = kmap_atomic(page, KM_USER0);
 	memset(kaddr, 0, PAGE_CACHE_SIZE);
 
-	de = (struct minix_dir_entry *)kaddr;
-	de->inode = inode->i_ino;
-	strcpy(de->name,".");
-	de = minix_next_entry(de, sbi);
-	de->inode = dir->i_ino;
-	strcpy(de->name,"..");
+	if (sbi->s_version == MINIX_V3) {
+		minix3_dirent *de3 = (minix3_dirent *)kaddr;
+
+		de3->inode = inode->i_ino;
+		strcpy(de3->name, ".");
+		de3 = minix_next_entry(de3, sbi);
+		de3->inode = dir->i_ino;
+		strcpy(de3->name, "..");
+	} else {
+		minix_dirent *de = (minix_dirent *)kaddr;
+
+		de->inode = inode->i_ino;
+		strcpy(de->name, ".");
+		de = minix_next_entry(de, sbi);
+		de->inode = dir->i_ino;
+		strcpy(de->name, "..");
+	}
 	kunmap_atomic(kaddr, KM_USER0);
 
 	err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
@@ -321,33 +373,41 @@
 	struct page *page = NULL;
 	unsigned long i, npages = dir_pages(inode);
 	struct minix_sb_info *sbi = minix_sb(inode->i_sb);
+	char *name;
+	__u32 inumber;
 
 	for (i = 0; i < npages; i++) {
-		char *kaddr;
-		minix_dirent * de;
-		page = dir_get_page(inode, i);
+		char *p, *kaddr, *limit;
 
+		page = dir_get_page(inode, i);
 		if (IS_ERR(page))
 			continue;
 
 		kaddr = (char *)page_address(page);
-		de = (minix_dirent *)kaddr;
-		kaddr += minix_last_byte(inode, i) - sbi->s_dirsize;
+		limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize;
+		for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
+			if (sbi->s_version == MINIX_V3) {
+				minix3_dirent *de3 = (minix3_dirent *)p;
+				name = de3->name;
+				inumber = de3->inode;
+			} else {
+				minix_dirent *de = (minix_dirent *)p;
+				name = de->name;
+				inumber = de->inode;
+			}
 
-		while ((char *)de <= kaddr) {
-			if (de->inode != 0) {
+			if (inumber != 0) {
 				/* check for . and .. */
-				if (de->name[0] != '.')
+				if (name[0] != '.')
 					goto not_empty;
-				if (!de->name[1]) {
-					if (de->inode != inode->i_ino)
+				if (!name[1]) {
+					if (inumber != inode->i_ino)
 						goto not_empty;
-				} else if (de->name[1] != '.')
+				} else if (name[1] != '.')
 					goto not_empty;
-				else if (de->name[2])
+				else if (name[2])
 					goto not_empty;
 			}
-			de = minix_next_entry(de, sbi);
 		}
 		dir_put_page(page);
 	}
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 40eac2e..f92baa1 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -26,7 +26,7 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations minix_file_inode_operations = {
+const struct inode_operations minix_file_inode_operations = {
 	.truncate	= minix_truncate,
 	.getattr	= minix_getattr,
 };
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 629e09b..92e383a 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -7,6 +7,7 @@
  *	Minix V2 fs support.
  *
  *  Modified for 680x0 by Andreas Schwab
+ *  Updated to filesystem version 3 by Daniel Aragones
  */
 
 #include <linux/module.h>
@@ -36,7 +37,8 @@
 	struct minix_sb_info *sbi = minix_sb(sb);
 
 	if (!(sb->s_flags & MS_RDONLY)) {
-		sbi->s_ms->s_state = sbi->s_mount_state;
+		if (sbi->s_version != MINIX_V3)	 /* s_state is now out from V3 sb */
+			sbi->s_ms->s_state = sbi->s_mount_state;
 		mark_buffer_dirty(sbi->s_sbh);
 	}
 	for (i = 0; i < sbi->s_imap_blocks; i++)
@@ -93,7 +95,7 @@
 	kmem_cache_destroy(minix_inode_cachep);
 }
 
-static struct super_operations minix_sops = {
+static const struct super_operations minix_sops = {
 	.alloc_inode	= minix_alloc_inode,
 	.destroy_inode	= minix_destroy_inode,
 	.read_inode	= minix_read_inode,
@@ -117,12 +119,17 @@
 		    !(sbi->s_mount_state & MINIX_VALID_FS))
 			return 0;
 		/* Mounting a rw partition read-only. */
-		ms->s_state = sbi->s_mount_state;
+		if (sbi->s_version != MINIX_V3)
+			ms->s_state = sbi->s_mount_state;
 		mark_buffer_dirty(sbi->s_sbh);
 	} else {
 	  	/* Mount a partition which is read-only, read-write. */
-		sbi->s_mount_state = ms->s_state;
-		ms->s_state &= ~MINIX_VALID_FS;
+		if (sbi->s_version != MINIX_V3) {
+			sbi->s_mount_state = ms->s_state;
+			ms->s_state &= ~MINIX_VALID_FS;
+		} else {
+			sbi->s_mount_state = MINIX_VALID_FS;
+		}
 		mark_buffer_dirty(sbi->s_sbh);
 
 		if (!(sbi->s_mount_state & MINIX_VALID_FS))
@@ -140,7 +147,8 @@
 	struct buffer_head *bh;
 	struct buffer_head **map;
 	struct minix_super_block *ms;
-	int i, block;
+	struct minix3_super_block *m3s = NULL;
+	unsigned long i, block;
 	struct inode *root_inode;
 	struct minix_sb_info *sbi;
 
@@ -192,6 +200,22 @@
 		sbi->s_dirsize = 32;
 		sbi->s_namelen = 30;
 		sbi->s_link_max = MINIX2_LINK_MAX;
+	} else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) {
+		m3s = (struct minix3_super_block *) bh->b_data;
+		s->s_magic = m3s->s_magic;
+		sbi->s_imap_blocks = m3s->s_imap_blocks;
+		sbi->s_zmap_blocks = m3s->s_zmap_blocks;
+		sbi->s_firstdatazone = m3s->s_firstdatazone;
+		sbi->s_log_zone_size = m3s->s_log_zone_size;
+		sbi->s_max_size = m3s->s_max_size;
+		sbi->s_ninodes = m3s->s_ninodes;
+		sbi->s_nzones = m3s->s_zones;
+		sbi->s_dirsize = 64;
+		sbi->s_namelen = 60;
+		sbi->s_version = MINIX_V3;
+		sbi->s_link_max = MINIX2_LINK_MAX;
+		sbi->s_mount_state = MINIX_VALID_FS;
+		sb_set_blocksize(s, m3s->s_blocksize);
 	} else
 		goto out_no_fs;
 
@@ -236,7 +260,8 @@
 		s->s_root->d_op = &minix_dentry_operations;
 
 	if (!(s->s_flags & MS_RDONLY)) {
-		ms->s_state &= ~MINIX_VALID_FS;
+		if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
+			ms->s_state &= ~MINIX_VALID_FS;
 		mark_buffer_dirty(bh);
 	}
 	if (!(sbi->s_mount_state & MINIX_VALID_FS))
@@ -278,8 +303,8 @@
 
 out_no_fs:
 	if (!silent)
-		printk("VFS: Can't find a Minix or Minix V2 filesystem "
-			"on device %s\n", s->s_id);
+		printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 "
+		       "on device %s.\n", s->s_id);
 out_release:
 	brelse(bh);
 	goto out;
@@ -344,7 +369,7 @@
 	.bmap = minix_bmap
 };
 
-static struct inode_operations minix_symlink_inode_operations = {
+static const struct inode_operations minix_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -537,12 +562,14 @@
 
 int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
+	struct inode *dir = dentry->d_parent->d_inode;
+	struct super_block *sb = dir->i_sb;
 	generic_fillattr(dentry->d_inode, stat);
 	if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
-		stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size);
+		stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
 	else
-		stat->blocks = (BLOCK_SIZE / 512) * V2_minix_blocks(stat->size);
-	stat->blksize = BLOCK_SIZE;
+		stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
+	stat->blksize = sb->s_blocksize;
 	return 0;
 }
 
diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c
index 429baf8..a731cab 100644
--- a/fs/minix/itree_common.c
+++ b/fs/minix/itree_common.c
@@ -23,7 +23,7 @@
 
 static inline block_t *block_end(struct buffer_head *bh)
 {
-	return (block_t *)((char*)bh->b_data + BLOCK_SIZE);
+	return (block_t *)((char*)bh->b_data + bh->b_size);
 }
 
 static inline Indirect *get_branch(struct inode *inode,
@@ -85,7 +85,7 @@
 		branch[n].key = cpu_to_block(nr);
 		bh = sb_getblk(inode->i_sb, parent);
 		lock_buffer(bh);
-		memset(bh->b_data, 0, BLOCK_SIZE);
+		memset(bh->b_data, 0, bh->b_size);
 		branch[n].bh = bh;
 		branch[n].p = (block_t*) bh->b_data + offsets[n];
 		*branch[n].p = branch[n].key;
@@ -292,6 +292,7 @@
 
 static inline void truncate (struct inode * inode)
 {
+	struct super_block *sb = inode->i_sb;
 	block_t *idata = i_data(inode);
 	int offsets[DEPTH];
 	Indirect chain[DEPTH];
@@ -301,7 +302,7 @@
 	int first_whole;
 	long iblock;
 
-	iblock = (inode->i_size + BLOCK_SIZE-1) >> 10;
+	iblock = (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits;
 	block_truncate_page(inode->i_mapping, inode->i_size, get_block);
 
 	n = block_to_path(inode, iblock, offsets);
@@ -346,15 +347,16 @@
 	mark_inode_dirty(inode);
 }
 
-static inline unsigned nblocks(loff_t size)
+static inline unsigned nblocks(loff_t size, struct super_block *sb)
 {
+	int k = sb->s_blocksize_bits - 10;
 	unsigned blocks, res, direct = DIRECT, i = DEPTH;
-	blocks = (size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+	blocks = (size + sb->s_blocksize - 1) >> (BLOCK_SIZE_BITS + k);
 	res = blocks;
 	while (--i && blocks > direct) {
 		blocks -= direct;
-		blocks += BLOCK_SIZE/sizeof(block_t) - 1;
-		blocks /= BLOCK_SIZE/sizeof(block_t);
+		blocks += sb->s_blocksize/sizeof(block_t) - 1;
+		blocks /= sb->s_blocksize/sizeof(block_t);
 		res += blocks;
 		direct = 1;
 	}
diff --git a/fs/minix/itree_v1.c b/fs/minix/itree_v1.c
index 656b134..1a5f3bf 100644
--- a/fs/minix/itree_v1.c
+++ b/fs/minix/itree_v1.c
@@ -55,7 +55,7 @@
 	truncate(inode);
 }
 
-unsigned V1_minix_blocks(loff_t size)
+unsigned V1_minix_blocks(loff_t size, struct super_block *sb)
 {
-	return nblocks(size);
+	return nblocks(size, sb);
 }
diff --git a/fs/minix/itree_v2.c b/fs/minix/itree_v2.c
index 9adcdc7..ad8f0de 100644
--- a/fs/minix/itree_v2.c
+++ b/fs/minix/itree_v2.c
@@ -23,10 +23,11 @@
 static int block_to_path(struct inode * inode, long block, int offsets[DEPTH])
 {
 	int n = 0;
+	struct super_block *sb = inode->i_sb;
 
 	if (block < 0) {
 		printk("minix_bmap: block<0\n");
-	} else if (block >= (minix_sb(inode->i_sb)->s_max_size/BLOCK_SIZE)) {
+	} else if (block >= (minix_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) {
 		printk("minix_bmap: block>big\n");
 	} else if (block < 7) {
 		offsets[n++] = block;
@@ -60,7 +61,7 @@
 	truncate(inode);
 }
 
-unsigned V2_minix_blocks(loff_t size)
+unsigned V2_minix_blocks(loff_t size, struct super_block *sb)
 {
-	return nblocks(size);
+	return nblocks(size, sb);
 }
diff --git a/fs/minix/minix.h b/fs/minix/minix.h
index c55b77c..73ef84f 100644
--- a/fs/minix/minix.h
+++ b/fs/minix/minix.h
@@ -7,11 +7,10 @@
  * truncated. Else they will be disallowed (ENAMETOOLONG).
  */
 #define NO_TRUNCATE 1
-
 #define INODE_VERSION(inode)	minix_sb(inode->i_sb)->s_version
-
 #define MINIX_V1		0x0001		/* original minix fs */
 #define MINIX_V2		0x0002		/* minix V2 fs */
+#define MINIX_V3		0x0003		/* minix V3 fs */
 
 /*
  * minix fs inode data in memory
@@ -52,12 +51,10 @@
 extern void minix_free_inode(struct inode * inode);
 extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi);
 extern int minix_new_block(struct inode * inode);
-extern void minix_free_block(struct inode * inode, int block);
+extern void minix_free_block(struct inode *inode, unsigned long block);
 extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
-
 extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 
-extern void V2_minix_truncate(struct inode *);
 extern void V1_minix_truncate(struct inode *);
 extern void V2_minix_truncate(struct inode *);
 extern void minix_truncate(struct inode *);
@@ -65,8 +62,8 @@
 extern void minix_set_inode(struct inode *, dev_t);
 extern int V1_minix_get_block(struct inode *, long, struct buffer_head *, int);
 extern int V2_minix_get_block(struct inode *, long, struct buffer_head *, int);
-extern unsigned V1_minix_blocks(loff_t);
-extern unsigned V2_minix_blocks(loff_t);
+extern unsigned V1_minix_blocks(loff_t, struct super_block *);
+extern unsigned V2_minix_blocks(loff_t, struct super_block *);
 
 extern struct minix_dir_entry *minix_find_entry(struct dentry*, struct page**);
 extern int minix_add_link(struct dentry*, struct inode*);
@@ -76,11 +73,10 @@
 extern void minix_set_link(struct minix_dir_entry*, struct page*, struct inode*);
 extern struct minix_dir_entry *minix_dotdot(struct inode*, struct page**);
 extern ino_t minix_inode_by_name(struct dentry*);
-
 extern int minix_sync_file(struct file *, struct dentry *, int);
 
-extern struct inode_operations minix_file_inode_operations;
-extern struct inode_operations minix_dir_inode_operations;
+extern const struct inode_operations minix_file_inode_operations;
+extern const struct inode_operations minix_dir_inode_operations;
 extern const struct file_operations minix_file_operations;
 extern const struct file_operations minix_dir_operations;
 extern struct dentry_operations minix_dentry_operations;
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index 299bb66..f4aa7a9 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -291,7 +291,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations minix_dir_inode_operations = {
+const struct inode_operations minix_dir_inode_operations = {
 	.create		= minix_create,
 	.lookup		= minix_lookup,
 	.link		= minix_link,
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 4524619..30f7d0a 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -646,7 +646,7 @@
 	return err;
 }
 
-static struct inode_operations msdos_dir_inode_operations = {
+static const struct inode_operations msdos_dir_inode_operations = {
 	.create		= msdos_create,
 	.lookup		= msdos_lookup,
 	.unlink		= msdos_unlink,
diff --git a/fs/namei.c b/fs/namei.c
index e4f108f..161e222 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2744,7 +2744,7 @@
 			mapping_gfp_mask(inode->i_mapping));
 }
 
-struct inode_operations page_symlink_inode_operations = {
+const struct inode_operations page_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 7374777..011ef0b 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -58,7 +58,7 @@
 #endif
 };
 
-struct inode_operations ncp_dir_inode_operations =
+const struct inode_operations ncp_dir_inode_operations =
 {
 	.create		= ncp_create,
 	.lookup		= ncp_lookup,
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index b91fea0..6b1f6d2 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -297,7 +297,7 @@
 	.fsync		= ncp_fsync,
 };
 
-struct inode_operations ncp_file_inode_operations =
+const struct inode_operations ncp_file_inode_operations =
 {
 	.setattr	= ncp_notify_change,
 };
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 67a90bf..14939dd 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -90,7 +90,7 @@
 	return 0;
 }
 
-static struct super_operations ncp_sops =
+static const struct super_operations ncp_sops =
 {
 	.alloc_inode	= ncp_alloc_inode,
 	.destroy_inode	= ncp_destroy_inode,
@@ -229,7 +229,7 @@
 }
 
 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-static struct inode_operations ncp_symlink_inode_operations = {
+static const struct inode_operations ncp_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 7933e2e..75f309c 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -71,6 +71,8 @@
 	complete(&nfs_callback_info.started);
 
 	for(;;) {
+		char buf[RPC_MAX_ADDRBUFLEN];
+
 		if (signalled()) {
 			if (nfs_callback_info.users == 0)
 				break;
@@ -88,8 +90,8 @@
 					__FUNCTION__, -err);
 			break;
 		}
-		dprintk("%s: request from %u.%u.%u.%u\n", __FUNCTION__,
-				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr));
+		dprintk("%s: request from %s\n", __FUNCTION__,
+				svc_print_addr(rqstp, buf, sizeof(buf)));
 		svc_process(rqstp);
 	}
 
@@ -106,7 +108,6 @@
 int nfs_callback_up(void)
 {
 	struct svc_serv *serv;
-	struct svc_sock *svsk;
 	int ret = 0;
 
 	lock_kernel();
@@ -119,17 +120,14 @@
 	ret = -ENOMEM;
 	if (!serv)
 		goto out_err;
-	/* FIXME: We don't want to register this socket with the portmapper */
-	ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport);
-	if (ret < 0)
+
+	ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport,
+							SVC_SOCK_ANONYMOUS);
+	if (ret <= 0)
 		goto out_destroy;
-	if (!list_empty(&serv->sv_permsocks)) {
-		svsk = list_entry(serv->sv_permsocks.next,
-				struct svc_sock, sk_list);
-		nfs_callback_tcpport = ntohs(inet_sk(svsk->sk_sk)->sport);
-		dprintk ("Callback port = 0x%x\n", nfs_callback_tcpport);
-	} else
-		BUG();
+	nfs_callback_tcpport = ret;
+	dprintk("Callback port = 0x%x\n", nfs_callback_tcpport);
+
 	ret = svc_create_thread(nfs_callback_svc, serv);
 	if (ret < 0)
 		goto out_destroy;
@@ -140,6 +138,8 @@
 	unlock_kernel();
 	return ret;
 out_destroy:
+	dprintk("Couldn't create callback socket or server thread; err = %d\n",
+		ret);
 	svc_destroy(serv);
 out_err:
 	nfs_callback_info.users--;
@@ -166,15 +166,19 @@
 
 static int nfs_callback_authenticate(struct svc_rqst *rqstp)
 {
-	struct sockaddr_in *addr = &rqstp->rq_addr;
+	struct sockaddr_in *addr = svc_addr_in(rqstp);
 	struct nfs_client *clp;
+	char buf[RPC_MAX_ADDRBUFLEN];
 
 	/* Don't talk to strangers */
 	clp = nfs_find_client(addr, 4);
 	if (clp == NULL)
 		return SVC_DROP;
-	dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr));
+
+	dprintk("%s: %s NFSv4 callback!\n", __FUNCTION__,
+			svc_print_addr(rqstp, buf, sizeof(buf)));
 	nfs_put_client(clp);
+
 	switch (rqstp->rq_authop->flavour) {
 		case RPC_AUTH_NULL:
 			if (rqstp->rq_proc != CB_NULL)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index f8ea1f5..849a202 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -176,7 +176,7 @@
 	status = decode_fh(xdr, &args->fh);
 	if (unlikely(status != 0))
 		goto out;
-	args->addr = &rqstp->rq_addr;
+	args->addr = svc_addr_in(rqstp);
 	status = decode_bitmap(xdr, args->bitmap);
 out:
 	dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
@@ -188,7 +188,7 @@
 	__be32 *p;
 	__be32 status;
 
-	args->addr = &rqstp->rq_addr;
+	args->addr = svc_addr_in(rqstp);
 	status = decode_stateid(xdr, &args->stateid);
 	if (unlikely(status != 0))
 		goto out;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 23ab145..ae9f36e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1173,7 +1173,7 @@
 	.show	= nfs_server_list_show,
 };
 
-static struct file_operations nfs_server_list_fops = {
+static const struct file_operations nfs_server_list_fops = {
 	.open		= nfs_server_list_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -1193,7 +1193,7 @@
 	.show	= nfs_volume_list_show,
 };
 
-static struct file_operations nfs_volume_list_fops = {
+static const struct file_operations nfs_volume_list_fops = {
 	.open		= nfs_volume_list_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index d9ba8cb..f03a770 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -65,7 +65,7 @@
 	.fsync		= nfs_fsync_dir,
 };
 
-struct inode_operations nfs_dir_inode_operations = {
+const struct inode_operations nfs_dir_inode_operations = {
 	.create		= nfs_create,
 	.lookup		= nfs_lookup,
 	.link		= nfs_link,
@@ -81,7 +81,7 @@
 };
 
 #ifdef CONFIG_NFS_V3
-struct inode_operations nfs3_dir_inode_operations = {
+const struct inode_operations nfs3_dir_inode_operations = {
 	.create		= nfs_create,
 	.lookup		= nfs_lookup,
 	.link		= nfs_link,
@@ -104,7 +104,7 @@
 #ifdef CONFIG_NFS_V4
 
 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
-struct inode_operations nfs4_dir_inode_operations = {
+const struct inode_operations nfs4_dir_inode_operations = {
 	.create		= nfs_create,
 	.lookup		= nfs_atomic_lookup,
 	.link		= nfs_link,
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 9e4a2b7..8e66b5a 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -68,14 +68,14 @@
 	.check_flags	= nfs_check_flags,
 };
 
-struct inode_operations nfs_file_inode_operations = {
+const struct inode_operations nfs_file_inode_operations = {
 	.permission	= nfs_permission,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
 };
 
 #ifdef CONFIG_NFS_V3
-struct inode_operations nfs3_file_inode_operations = {
+const struct inode_operations nfs3_file_inode_operations = {
 	.permission	= nfs_permission,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 371b804..7f86e65 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -155,12 +155,12 @@
 	goto out;
 }
 
-struct inode_operations nfs_mountpoint_inode_operations = {
+const struct inode_operations nfs_mountpoint_inode_operations = {
 	.follow_link	= nfs_follow_mountpoint,
 	.getattr	= nfs_getattr,
 };
 
-struct inode_operations nfs_referral_inode_operations = {
+const struct inode_operations nfs_referral_inode_operations = {
 	.follow_link	= nfs_follow_mountpoint,
 };
 
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index c26cd97..e234176 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -151,7 +151,7 @@
 };
 
 extern struct dentry_operations nfs4_dentry_operations;
-extern struct inode_operations nfs4_dir_inode_operations;
+extern const struct inode_operations nfs4_dir_inode_operations;
 
 /* inode.c */
 extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b3fd29b..1daee65 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3625,7 +3625,7 @@
 	.recover_lock	= nfs4_lock_expired,
 };
 
-static struct inode_operations nfs4_file_inode_operations = {
+static const struct inode_operations nfs4_file_inode_operations = {
 	.permission	= nfs_permission,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 28108c8..baa2886 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -44,6 +44,7 @@
 #include <linux/vfs.h>
 #include <linux/inet.h>
 #include <linux/nfs_xdr.h>
+#include <linux/magic.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -81,7 +82,7 @@
 	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
 
-static struct super_operations nfs_sops = {
+static const struct super_operations nfs_sops = {
 	.alloc_inode	= nfs_alloc_inode,
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
@@ -125,7 +126,7 @@
 	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
 
-static struct super_operations nfs4_sops = {
+static const struct super_operations nfs4_sops = {
 	.alloc_inode	= nfs_alloc_inode,
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 525c136..f4a0548 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -78,7 +78,7 @@
 /*
  * symlinks can't do much...
  */
-struct inode_operations nfs_symlink_inode_operations = {
+const struct inode_operations nfs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= nfs_follow_link,
 	.put_link	= page_put_link,
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9de89df..9e40679 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -714,7 +714,7 @@
 nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		  struct nfsd4_setclientid *setclid)
 {
-	__be32 			ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	struct sockaddr_in	*sin = svc_addr_in(rqstp);
 	struct xdr_netobj 	clname = { 
 		.len = setclid->se_namelen,
 		.data = setclid->se_name,
@@ -749,7 +749,7 @@
 		 */
 		status = nfserr_clid_inuse;
 		if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
-				|| conf->cl_addr != ip_addr) {
+				|| conf->cl_addr != sin->sin_addr.s_addr) {
 			printk("NFSD: setclientid: string in use by client"
 			"(clientid %08x/%08x)\n",
 			conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
@@ -769,7 +769,7 @@
 		if (new == NULL)
 			goto out;
 		copy_verf(new, &clverifier);
-		new->cl_addr = ip_addr;
+		new->cl_addr = sin->sin_addr.s_addr;
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		gen_clid(new);
 		gen_confirm(new);
@@ -801,7 +801,7 @@
 		if (new == NULL)
 			goto out;
 		copy_verf(new,&conf->cl_verifier);
-		new->cl_addr = ip_addr;
+		new->cl_addr = sin->sin_addr.s_addr;
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		copy_clid(new, conf);
 		gen_confirm(new);
@@ -820,7 +820,7 @@
 		if (new == NULL)
 			goto out;
 		copy_verf(new,&clverifier);
-		new->cl_addr = ip_addr;
+		new->cl_addr = sin->sin_addr.s_addr;
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		gen_clid(new);
 		gen_confirm(new);
@@ -847,7 +847,7 @@
 		if (new == NULL)
 			goto out;
 		copy_verf(new,&clverifier);
-		new->cl_addr = ip_addr;
+		new->cl_addr = sin->sin_addr.s_addr;
 		copy_cred(&new->cl_cred,&rqstp->rq_cred);
 		gen_clid(new);
 		gen_confirm(new);
@@ -881,7 +881,7 @@
 			 struct nfsd4_compound_state *cstate,
 			 struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
-	__be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
+	struct sockaddr_in *sin = svc_addr_in(rqstp);
 	struct nfs4_client *conf, *unconf;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
@@ -900,9 +900,9 @@
 	unconf = find_unconfirmed_client(clid);
 
 	status = nfserr_clid_inuse;
-	if (conf && conf->cl_addr != ip_addr)
+	if (conf && conf->cl_addr != sin->sin_addr.s_addr)
 		goto out;
-	if (unconf && unconf->cl_addr != ip_addr)
+	if (unconf && unconf->cl_addr != sin->sin_addr.s_addr)
 		goto out;
 
 	if ((conf && unconf) && 
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index f90d704..578f2c9 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -185,7 +185,7 @@
 	rp->c_state = RC_INPROG;
 	rp->c_xid = xid;
 	rp->c_proc = proc;
-	rp->c_addr = rqstp->rq_addr;
+	memcpy(&rp->c_addr, svc_addr_in(rqstp), sizeof(rp->c_addr));
 	rp->c_prot = proto;
 	rp->c_vers = vers;
 	rp->c_timestamp = jiffies;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index c59d6fb..a0b4282 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -20,6 +20,7 @@
 #include <linux/mount.h>
 #include <asm/pgtable.h>
 
+#include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 
@@ -180,10 +181,10 @@
 		/* Check if the request originated from a secure port. */
 		error = nfserr_perm;
 		if (!rqstp->rq_secure && EX_SECURE(exp)) {
+			char buf[RPC_MAX_ADDRBUFLEN];
 			printk(KERN_WARNING
-			       "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n",
-			       NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
-			       ntohs(rqstp->rq_addr.sin_port));
+			       "nfsd: request from insecure port %s!\n",
+			       svc_print_addr(rqstp, buf, sizeof(buf)));
 			goto out;
 		}
 
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index ec983b7..5cc2eec 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -19,6 +19,7 @@
 #include <linux/unistd.h>
 #include <linux/slab.h>
 
+#include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/cache.h>
@@ -147,10 +148,10 @@
 	 */
 
 	if (NFSSVC_MAXBLKSIZE_V2 < argp->count) {
+		char buf[RPC_MAX_ADDRBUFLEN];
 		printk(KERN_NOTICE
-			"oversized read request from %u.%u.%u.%u:%d (%d bytes)\n",
-				NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
-				ntohs(rqstp->rq_addr.sin_port),
+			"oversized read request from %s (%d bytes)\n",
+				svc_print_addr(rqstp, buf, sizeof(buf)),
 				argp->count);
 		argp->count = NFSSVC_MAXBLKSIZE_V2;
 	}
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index fbf5d51..d7759ce 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -235,7 +235,8 @@
 
 	error = lockd_up(IPPROTO_UDP);
 	if (error >= 0) {
-		error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
+		error = svc_makesock(nfsd_serv, IPPROTO_UDP, port,
+					SVC_SOCK_DEFAULTS);
 		if (error < 0)
 			lockd_down();
 	}
@@ -245,7 +246,8 @@
 #ifdef CONFIG_NFSD_TCP
 	error = lockd_up(IPPROTO_TCP);
 	if (error >= 0) {
-		error = svc_makesock(nfsd_serv, IPPROTO_TCP, port);
+		error = svc_makesock(nfsd_serv, IPPROTO_TCP, port,
+					SVC_SOCK_DEFAULTS);
 		if (error < 0)
 			lockd_down();
 	}
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index c577d8e..7659cc1 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -1921,7 +1921,7 @@
 	u32 attr_len = 0; /* Silence stupid gcc warning. */
 	bool mp_rebuilt;
 
-#ifdef NTFS_DEBUG
+#ifdef DEBUG
 	read_lock_irqsave(&ni->size_lock, flags);
 	allocated_size = ni->allocated_size;
 	read_unlock_irqrestore(&ni->size_lock, flags);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 076c942..d69c459 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2328,7 +2328,7 @@
 						    the data source. */
 };
 
-struct inode_operations ntfs_file_inode_ops = {
+const struct inode_operations ntfs_file_inode_ops = {
 #ifdef NTFS_RW
 	.truncate	= ntfs_truncate_vfs,
 	.setattr	= ntfs_setattr,
@@ -2337,4 +2337,4 @@
 
 const struct file_operations ntfs_empty_file_ops = {};
 
-struct inode_operations ntfs_empty_inode_ops = {};
+const struct inode_operations ntfs_empty_inode_ops = {};
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index eddb224..bff01a5 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -359,7 +359,7 @@
 /**
  * Inode operations for directories.
  */
-struct inode_operations ntfs_dir_inode_ops = {
+const struct inode_operations ntfs_dir_inode_ops = {
 	.lookup	= ntfs_lookup,	/* VFS: Lookup directory. */
 };
 
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index a12847a..d73f5a9 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -61,13 +61,13 @@
 extern const struct address_space_operations ntfs_mst_aops;
 
 extern const struct  file_operations ntfs_file_ops;
-extern struct inode_operations ntfs_file_inode_ops;
+extern const struct inode_operations ntfs_file_inode_ops;
 
 extern const struct  file_operations ntfs_dir_ops;
-extern struct inode_operations ntfs_dir_inode_ops;
+extern const struct inode_operations ntfs_dir_inode_ops;
 
 extern const struct  file_operations ntfs_empty_file_ops;
-extern struct inode_operations ntfs_empty_inode_ops;
+extern const struct inode_operations ntfs_empty_inode_ops;
 
 extern struct export_operations ntfs_export_ops;
 
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index babf94d..1594c90 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2699,7 +2699,7 @@
 /**
  * The complete super operations.
  */
-static struct super_operations ntfs_sops = {
+static const struct super_operations ntfs_sops = {
 	.alloc_inode	= ntfs_alloc_big_inode,	  /* VFS: Allocate new inode. */
 	.destroy_inode	= ntfs_destroy_big_inode, /* VFS: Deallocate inode. */
 #ifdef NTFS_RW
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index b7f0ba9..de952eb 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -61,11 +61,11 @@
 #define MLOG_MASK_PREFIX ML_DLMFS
 #include "cluster/masklog.h"
 
-static struct super_operations dlmfs_ops;
-static struct file_operations dlmfs_file_operations;
-static struct inode_operations dlmfs_dir_inode_operations;
-static struct inode_operations dlmfs_root_inode_operations;
-static struct inode_operations dlmfs_file_inode_operations;
+static const struct super_operations dlmfs_ops;
+static const struct file_operations dlmfs_file_operations;
+static const struct inode_operations dlmfs_dir_inode_operations;
+static const struct inode_operations dlmfs_root_inode_operations;
+static const struct inode_operations dlmfs_file_inode_operations;
 static struct kmem_cache *dlmfs_inode_cache;
 
 struct workqueue_struct *user_dlm_worker;
@@ -540,27 +540,27 @@
 	return 0;
 }
 
-static struct file_operations dlmfs_file_operations = {
+static const struct file_operations dlmfs_file_operations = {
 	.open		= dlmfs_file_open,
 	.release	= dlmfs_file_release,
 	.read		= dlmfs_file_read,
 	.write		= dlmfs_file_write,
 };
 
-static struct inode_operations dlmfs_dir_inode_operations = {
+static const struct inode_operations dlmfs_dir_inode_operations = {
 	.create		= dlmfs_create,
 	.lookup		= simple_lookup,
 	.unlink		= dlmfs_unlink,
 };
 
 /* this way we can restrict mkdir to only the toplevel of the fs. */
-static struct inode_operations dlmfs_root_inode_operations = {
+static const struct inode_operations dlmfs_root_inode_operations = {
 	.lookup		= simple_lookup,
 	.mkdir		= dlmfs_mkdir,
 	.rmdir		= simple_rmdir,
 };
 
-static struct super_operations dlmfs_ops = {
+static const struct super_operations dlmfs_ops = {
 	.statfs		= simple_statfs,
 	.alloc_inode	= dlmfs_alloc_inode,
 	.destroy_inode	= dlmfs_destroy_inode,
@@ -568,7 +568,7 @@
 	.drop_inode	= generic_delete_inode,
 };
 
-static struct inode_operations dlmfs_file_inode_operations = {
+static const struct inode_operations dlmfs_file_inode_operations = {
 	.getattr	= simple_getattr,
 };
 
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index 10953a5..f2cd3bf 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -1365,13 +1365,13 @@
 	return ret;
 }
 
-struct inode_operations ocfs2_file_iops = {
+const struct inode_operations ocfs2_file_iops = {
 	.setattr	= ocfs2_setattr,
 	.getattr	= ocfs2_getattr,
 	.permission	= ocfs2_permission,
 };
 
-struct inode_operations ocfs2_special_file_iops = {
+const struct inode_operations ocfs2_special_file_iops = {
 	.setattr	= ocfs2_setattr,
 	.getattr	= ocfs2_getattr,
 	.permission	= ocfs2_permission,
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
index 601a453..cc973f0 100644
--- a/fs/ocfs2/file.h
+++ b/fs/ocfs2/file.h
@@ -28,8 +28,8 @@
 
 extern const struct file_operations ocfs2_fops;
 extern const struct file_operations ocfs2_dops;
-extern struct inode_operations ocfs2_file_iops;
-extern struct inode_operations ocfs2_special_file_iops;
+extern const struct inode_operations ocfs2_file_iops;
+extern const struct inode_operations ocfs2_special_file_iops;
 struct ocfs2_alloc_context;
 
 enum ocfs2_alloc_restarted {
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index f3d7803..f7fa52b 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2306,7 +2306,7 @@
 	return status;
 }
 
-struct inode_operations ocfs2_dir_iops = {
+const struct inode_operations ocfs2_dir_iops = {
 	.create		= ocfs2_create,
 	.lookup		= ocfs2_lookup,
 	.link		= ocfs2_link,
diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h
index 8425944..0975c7b 100644
--- a/fs/ocfs2/namei.h
+++ b/fs/ocfs2/namei.h
@@ -26,7 +26,7 @@
 #ifndef OCFS2_NAMEI_H
 #define OCFS2_NAMEI_H
 
-extern struct inode_operations ocfs2_dir_iops;
+extern const struct inode_operations ocfs2_dir_iops;
 
 struct dentry *ocfs2_get_parent(struct dentry *child);
 
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 6e300a8..6534f92 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -116,7 +116,7 @@
 
 static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
 
-static struct super_operations ocfs2_sops = {
+static const struct super_operations ocfs2_sops = {
 	.statfs		= ocfs2_statfs,
 	.alloc_inode	= ocfs2_alloc_inode,
 	.destroy_inode	= ocfs2_destroy_inode,
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index 03b0191..40dc1a5 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -170,12 +170,12 @@
 	return ERR_PTR(status);
 }
 
-struct inode_operations ocfs2_symlink_inode_operations = {
+const struct inode_operations ocfs2_symlink_inode_operations = {
 	.readlink	= page_readlink,
 	.follow_link	= ocfs2_follow_link,
 	.getattr	= ocfs2_getattr,
 };
-struct inode_operations ocfs2_fast_symlink_inode_operations = {
+const struct inode_operations ocfs2_fast_symlink_inode_operations = {
 	.readlink	= ocfs2_readlink,
 	.follow_link	= ocfs2_follow_link,
 	.getattr	= ocfs2_getattr,
diff --git a/fs/ocfs2/symlink.h b/fs/ocfs2/symlink.h
index 1ea9e4d..65a6c9c 100644
--- a/fs/ocfs2/symlink.h
+++ b/fs/ocfs2/symlink.h
@@ -26,8 +26,8 @@
 #ifndef OCFS2_SYMLINK_H
 #define OCFS2_SYMLINK_H
 
-extern struct inode_operations ocfs2_symlink_inode_operations;
-extern struct inode_operations ocfs2_fast_symlink_inode_operations;
+extern const struct inode_operations ocfs2_symlink_inode_operations;
+extern const struct inode_operations ocfs2_fast_symlink_inode_operations;
 
 /*
  * Test whether an inode is a fast symlink.
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 99c0bc3..bde1c16 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -169,7 +169,7 @@
 
 static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *);
 
-static struct inode_operations openprom_inode_operations = {
+static const struct inode_operations openprom_inode_operations = {
 	.lookup		= openpromfs_lookup,
 };
 
@@ -364,7 +364,7 @@
 	return 0;
 }
 
-static struct super_operations openprom_sops = { 
+static const struct super_operations openprom_sops = {
 	.alloc_inode	= openprom_alloc_inode,
 	.destroy_inode	= openprom_destroy_inode,
 	.read_inode	= openprom_read_inode,
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 70e4fab..07c9cdb 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -351,7 +351,7 @@
 		struct signal_struct *sig = task->signal;
 
 		if (sig->tty) {
-			tty_pgrp = sig->tty->pgrp;
+			tty_pgrp = pid_nr(sig->tty->pgrp);
 			tty_nr = new_encode_dev(tty_devnum(sig->tty));
 		}
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 7fb37d6..4f5745a 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -93,8 +93,8 @@
 	int len;
 	char *name;
 	mode_t mode;
-	struct inode_operations *iop;
-	struct file_operations *fop;
+	const struct inode_operations *iop;
+	const struct file_operations *fop;
 	union proc_op op;
 };
 
@@ -352,7 +352,7 @@
 	return error;
 }
 
-static struct inode_operations proc_def_inode_operations = {
+static const struct inode_operations proc_def_inode_operations = {
 	.setattr	= proc_setattr,
 };
 
@@ -424,7 +424,7 @@
 	return res;
 }
 
-static struct file_operations proc_mounts_operations = {
+static const struct file_operations proc_mounts_operations = {
 	.open		= mounts_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -462,7 +462,7 @@
 	return ret;
 }
 
-static struct file_operations proc_mountstats_operations = {
+static const struct file_operations proc_mountstats_operations = {
 	.open		= mountstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -501,7 +501,7 @@
 	return length;
 }
 
-static struct file_operations proc_info_file_operations = {
+static const struct file_operations proc_info_file_operations = {
 	.read		= proc_info_read,
 };
 
@@ -646,7 +646,7 @@
 	return file->f_pos;
 }
 
-static struct file_operations proc_mem_operations = {
+static const struct file_operations proc_mem_operations = {
 	.llseek		= mem_lseek,
 	.read		= mem_read,
 	.write		= mem_write,
@@ -710,7 +710,7 @@
 	return end - buffer;
 }
 
-static struct file_operations proc_oom_adjust_operations = {
+static const struct file_operations proc_oom_adjust_operations = {
 	.read		= oom_adjust_read,
 	.write		= oom_adjust_write,
 };
@@ -777,7 +777,7 @@
 	return length;
 }
 
-static struct file_operations proc_loginuid_operations = {
+static const struct file_operations proc_loginuid_operations = {
 	.read		= proc_loginuid_read,
 	.write		= proc_loginuid_write,
 };
@@ -849,7 +849,7 @@
 	return result;
 }
 
-static struct file_operations proc_seccomp_operations = {
+static const struct file_operations proc_seccomp_operations = {
 	.read		= seccomp_read,
 	.write		= seccomp_write,
 };
@@ -908,7 +908,7 @@
 	return end - buffer;
 }
 
-static struct file_operations proc_fault_inject_operations = {
+static const struct file_operations proc_fault_inject_operations = {
 	.read		= proc_fault_inject_read,
 	.write		= proc_fault_inject_write,
 };
@@ -980,7 +980,7 @@
 	return error;
 }
 
-static struct inode_operations proc_pid_link_inode_operations = {
+static const struct inode_operations proc_pid_link_inode_operations = {
 	.readlink	= proc_pid_readlink,
 	.follow_link	= proc_pid_follow_link,
 	.setattr	= proc_setattr,
@@ -1408,7 +1408,7 @@
 	return retval;
 }
 
-static struct file_operations proc_fd_operations = {
+static const struct file_operations proc_fd_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_readfd,
 };
@@ -1416,7 +1416,7 @@
 /*
  * proc directories can do almost nothing..
  */
-static struct inode_operations proc_fd_inode_operations = {
+static const struct inode_operations proc_fd_inode_operations = {
 	.lookup		= proc_lookupfd,
 	.setattr	= proc_setattr,
 };
@@ -1623,7 +1623,7 @@
 	return length;
 }
 
-static struct file_operations proc_pid_attr_operations = {
+static const struct file_operations proc_pid_attr_operations = {
 	.read		= proc_pid_attr_read,
 	.write		= proc_pid_attr_write,
 };
@@ -1644,7 +1644,7 @@
 				   attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff));
 }
 
-static struct file_operations proc_attr_dir_operations = {
+static const struct file_operations proc_attr_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_attr_dir_readdir,
 };
@@ -1656,7 +1656,7 @@
 				  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
 }
 
-static struct inode_operations proc_attr_dir_inode_operations = {
+static const struct inode_operations proc_attr_dir_inode_operations = {
 	.lookup		= proc_attr_dir_lookup,
 	.getattr	= pid_getattr,
 	.setattr	= proc_setattr,
@@ -1682,7 +1682,7 @@
 	return ERR_PTR(vfs_follow_link(nd,tmp));
 }
 
-static struct inode_operations proc_self_inode_operations = {
+static const struct inode_operations proc_self_inode_operations = {
 	.readlink	= proc_self_readlink,
 	.follow_link	= proc_self_follow_link,
 };
@@ -1834,8 +1834,8 @@
 /*
  * Thread groups
  */
-static struct file_operations proc_task_operations;
-static struct inode_operations proc_task_inode_operations;
+static const struct file_operations proc_task_operations;
+static const struct inode_operations proc_task_inode_operations;
 
 static struct pid_entry tgid_base_stuff[] = {
 	DIR("task",       S_IRUGO|S_IXUGO, task),
@@ -1894,7 +1894,7 @@
 				   tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
 }
 
-static struct file_operations proc_tgid_base_operations = {
+static const struct file_operations proc_tgid_base_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_tgid_base_readdir,
 };
@@ -1904,7 +1904,7 @@
 				  tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
 }
 
-static struct inode_operations proc_tgid_base_inode_operations = {
+static const struct inode_operations proc_tgid_base_inode_operations = {
 	.lookup		= proc_tgid_base_lookup,
 	.getattr	= pid_getattr,
 	.setattr	= proc_setattr,
@@ -2177,12 +2177,12 @@
 				  tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
 }
 
-static struct file_operations proc_tid_base_operations = {
+static const struct file_operations proc_tid_base_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_tid_base_readdir,
 };
 
-static struct inode_operations proc_tid_base_inode_operations = {
+static const struct inode_operations proc_tid_base_inode_operations = {
 	.lookup		= proc_tid_base_lookup,
 	.getattr	= pid_getattr,
 	.setattr	= proc_setattr,
@@ -2408,13 +2408,13 @@
 	return 0;
 }
 
-static struct inode_operations proc_task_inode_operations = {
+static const struct inode_operations proc_task_inode_operations = {
 	.lookup		= proc_task_lookup,
 	.getattr	= proc_task_getattr,
 	.setattr	= proc_setattr,
 };
 
-static struct file_operations proc_task_operations = {
+static const struct file_operations proc_task_operations = {
 	.read		= generic_read_dir,
 	.readdir	= proc_task_readdir,
 };
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 853cb87..0cdc00d 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -39,7 +39,7 @@
 	return !memcmp(name, de->name, len);
 }
 
-static struct file_operations proc_file_operations = {
+static const struct file_operations proc_file_operations = {
 	.llseek		= proc_file_lseek,
 	.read		= proc_file_read,
 	.write		= proc_file_write,
@@ -265,7 +265,7 @@
 	return 0;
 }
 
-static struct inode_operations proc_file_inode_operations = {
+static const struct inode_operations proc_file_inode_operations = {
 	.setattr	= proc_notify_change,
 };
 
@@ -357,7 +357,7 @@
 	return NULL;
 }
 
-static struct inode_operations proc_link_inode_operations = {
+static const struct inode_operations proc_link_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= proc_follow_link,
 };
@@ -497,7 +497,7 @@
  * use the in-memory "struct proc_dir_entry" tree to parse
  * the /proc directory.
  */
-static struct file_operations proc_dir_operations = {
+static const struct file_operations proc_dir_operations = {
 	.read			= generic_read_dir,
 	.readdir		= proc_readdir,
 };
@@ -505,7 +505,7 @@
 /*
  * proc directories can do almost nothing..
  */
-static struct inode_operations proc_dir_inode_operations = {
+static const struct inode_operations proc_dir_inode_operations = {
 	.lookup		= proc_lookup,
 	.getattr	= proc_getattr,
 	.setattr	= proc_notify_change,
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index e26945b..f6722be 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -132,7 +132,7 @@
 	return 0;
 }
 
-static struct super_operations proc_sops = { 
+static const struct super_operations proc_sops = {
 	.alloc_inode	= proc_alloc_inode,
 	.destroy_inode	= proc_destroy_inode,
 	.read_inode	= proc_read_inode,
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 987c773..277dcd6 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -38,13 +38,13 @@
 extern int proc_pid_status(struct task_struct *, char *);
 extern int proc_pid_statm(struct task_struct *, char *);
 
-extern struct file_operations proc_maps_operations;
-extern struct file_operations proc_numa_maps_operations;
-extern struct file_operations proc_smaps_operations;
+extern const struct file_operations proc_maps_operations;
+extern const struct file_operations proc_numa_maps_operations;
+extern const struct file_operations proc_smaps_operations;
 
-extern struct file_operations proc_maps_operations;
-extern struct file_operations proc_numa_maps_operations;
-extern struct file_operations proc_smaps_operations;
+extern const struct file_operations proc_maps_operations;
+extern const struct file_operations proc_numa_maps_operations;
+extern const struct file_operations proc_smaps_operations;
 
 
 void free_proc_entry(struct proc_dir_entry *de);
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
index 5ec6725..22f789d 100644
--- a/fs/proc/nommu.c
+++ b/fs/proc/nommu.c
@@ -128,7 +128,7 @@
 	return seq_open(file, &proc_nommu_vma_list_seqop);
 }
 
-static struct file_operations proc_nommu_vma_list_operations = {
+static const struct file_operations proc_nommu_vma_list_operations = {
 	.open    = proc_nommu_vma_list_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 5e2d435..e2c4c0a 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -223,7 +223,7 @@
 	return seq_open(file, &fragmentation_op);
 }
 
-static struct file_operations fragmentation_file_operations = {
+static const struct file_operations fragmentation_file_operations = {
 	.open		= fragmentation_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -236,7 +236,7 @@
 	return seq_open(file, &zoneinfo_op);
 }
 
-static struct file_operations proc_zoneinfo_file_operations = {
+static const struct file_operations proc_zoneinfo_file_operations = {
 	.open		= zoneinfo_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -261,7 +261,7 @@
 	return seq_open(file, &cpuinfo_op);
 }
 
-static struct file_operations proc_cpuinfo_operations = {
+static const struct file_operations proc_cpuinfo_operations = {
 	.open		= cpuinfo_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -320,7 +320,7 @@
 	return seq_open(filp, &devinfo_ops);
 }
 
-static struct file_operations proc_devinfo_operations = {
+static const struct file_operations proc_devinfo_operations = {
 	.open		= devinfo_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -332,7 +332,7 @@
 {
 	return seq_open(file, &vmstat_op);
 }
-static struct file_operations proc_vmstat_file_operations = {
+static const struct file_operations proc_vmstat_file_operations = {
 	.open		= vmstat_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -363,7 +363,7 @@
 {
 	return seq_open(file, &partitions_op);
 }
-static struct file_operations proc_partitions_operations = {
+static const struct file_operations proc_partitions_operations = {
 	.open		= partitions_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -375,7 +375,7 @@
 {
 	return seq_open(file, &diskstats_op);
 }
-static struct file_operations proc_diskstats_operations = {
+static const struct file_operations proc_diskstats_operations = {
 	.open		= diskstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -389,7 +389,7 @@
 {
 	return seq_open(file, &modules_op);
 }
-static struct file_operations proc_modules_operations = {
+static const struct file_operations proc_modules_operations = {
 	.open		= modules_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -404,7 +404,7 @@
 {
 	return seq_open(file, &slabinfo_op);
 }
-static struct file_operations proc_slabinfo_operations = {
+static const struct file_operations proc_slabinfo_operations = {
 	.open		= slabinfo_open,
 	.read		= seq_read,
 	.write		= slabinfo_write,
@@ -438,7 +438,7 @@
 	return seq_release(inode, file);
 }
 
-static struct file_operations proc_slabstats_operations = {
+static const struct file_operations proc_slabstats_operations = {
 	.open		= slabstats_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -551,7 +551,7 @@
 		kfree(buf);
 	return res;
 }
-static struct file_operations proc_stat_operations = {
+static const struct file_operations proc_stat_operations = {
 	.open		= stat_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -593,7 +593,7 @@
 	return seq_open(filp, &int_seq_ops);
 }
 
-static struct file_operations proc_interrupts_operations = {
+static const struct file_operations proc_interrupts_operations = {
 	.open		= interrupts_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -650,7 +650,7 @@
 	return count;
 }
 
-static struct file_operations proc_sysrq_trigger_operations = {
+static const struct file_operations proc_sysrq_trigger_operations = {
 	.write		= write_sysrq_trigger,
 };
 #endif
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index 15c4455..c1bbfbe 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -138,7 +138,7 @@
 	return seq_open(file, &tty_drivers_op);
 }
 
-static struct file_operations proc_tty_drivers_operations = {
+static const struct file_operations proc_tty_drivers_operations = {
 	.open		= tty_drivers_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 64d242b6..af15445 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -136,7 +136,7 @@
  * <pid> directories. Thus we don't use the generic
  * directory handling functions for that..
  */
-static struct file_operations proc_root_operations = {
+static const struct file_operations proc_root_operations = {
 	.read		 = generic_read_dir,
 	.readdir	 = proc_root_readdir,
 };
@@ -144,7 +144,7 @@
 /*
  * proc root can do almost nothing..
  */
-static struct inode_operations proc_root_inode_operations = {
+static const struct inode_operations proc_root_inode_operations = {
 	.lookup		= proc_root_lookup,
 	.getattr	= proc_root_getattr,
 };
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 55ade0d..7445980c 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -434,7 +434,7 @@
 	return do_maps_open(inode, file, &proc_pid_maps_op);
 }
 
-struct file_operations proc_maps_operations = {
+const struct file_operations proc_maps_operations = {
 	.open		= maps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -456,7 +456,7 @@
 	return do_maps_open(inode, file, &proc_pid_numa_maps_op);
 }
 
-struct file_operations proc_numa_maps_operations = {
+const struct file_operations proc_numa_maps_operations = {
 	.open		= numa_maps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -469,7 +469,7 @@
 	return do_maps_open(inode, file, &proc_pid_smaps_op);
 }
 
-struct file_operations proc_smaps_operations = {
+const struct file_operations proc_smaps_operations = {
 	.open		= smaps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index fcc5caf..7cddf6b 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -220,7 +220,7 @@
 	return ret;
 }
 
-struct file_operations proc_maps_operations = {
+const struct file_operations proc_maps_operations = {
 	.open		= maps_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index c94db1d..ea9ffef 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -87,7 +87,7 @@
 	.fsync		= file_fsync,
 };
 
-struct inode_operations qnx4_dir_inode_operations =
+const struct inode_operations qnx4_dir_inode_operations =
 {
 	.lookup		= qnx4_lookup,
 #ifdef CONFIG_QNX4FS_RW
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index 467e5ac..4464998 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -33,7 +33,7 @@
 #endif
 };
 
-struct inode_operations qnx4_file_inode_operations =
+const struct inode_operations qnx4_file_inode_operations =
 {
 #ifdef CONFIG_QNX4FS_RW
 	.truncate	= qnx4_truncate,
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index c047dc6..83bc8e7 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -30,7 +30,7 @@
 #define QNX4_VERSION  4
 #define QNX4_BMNAME   ".bitmap"
 
-static struct super_operations qnx4_sops;
+static const struct super_operations qnx4_sops;
 
 #ifdef CONFIG_QNX4FS_RW
 
@@ -129,7 +129,7 @@
 static int qnx4_remount(struct super_block *sb, int *flags, char *data);
 static int qnx4_statfs(struct dentry *, struct kstatfs *);
 
-static struct super_operations qnx4_sops =
+static const struct super_operations qnx4_sops =
 {
 	.alloc_inode	= qnx4_alloc_inode,
 	.destroy_inode	= qnx4_destroy_inode,
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index b935a3d..2f14774 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -45,6 +45,6 @@
 	.llseek		= generic_file_llseek,
 };
 
-struct inode_operations ramfs_file_inode_operations = {
+const struct inode_operations ramfs_file_inode_operations = {
 	.getattr	= simple_getattr,
 };
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index d05e09a..d3fd7c6 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -47,7 +47,7 @@
 	.llseek			= generic_file_llseek,
 };
 
-struct inode_operations ramfs_file_inode_operations = {
+const struct inode_operations ramfs_file_inode_operations = {
 	.setattr		= ramfs_nommu_setattr,
 	.getattr		= simple_getattr,
 };
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 2faf4cd..ff1f763 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -40,8 +40,8 @@
 /* some random number */
 #define RAMFS_MAGIC	0x858458f6
 
-static struct super_operations ramfs_ops;
-static struct inode_operations ramfs_dir_inode_operations;
+static const struct super_operations ramfs_ops;
+static const struct inode_operations ramfs_dir_inode_operations;
 
 static struct backing_dev_info ramfs_backing_dev_info = {
 	.ra_pages	= 0,	/* No readahead */
@@ -143,7 +143,7 @@
 	return error;
 }
 
-static struct inode_operations ramfs_dir_inode_operations = {
+static const struct inode_operations ramfs_dir_inode_operations = {
 	.create		= ramfs_create,
 	.lookup		= simple_lookup,
 	.link		= simple_link,
@@ -155,7 +155,7 @@
 	.rename		= simple_rename,
 };
 
-static struct super_operations ramfs_ops = {
+static const struct super_operations ramfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
 };
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h
index c2bb58e..af7cc07 100644
--- a/fs/ramfs/internal.h
+++ b/fs/ramfs/internal.h
@@ -12,4 +12,4 @@
 
 extern const struct address_space_operations ramfs_aops;
 extern const struct file_operations ramfs_file_operations;
-extern struct inode_operations ramfs_file_inode_operations;
+extern const struct inode_operations ramfs_file_inode_operations;
diff --git a/fs/read_write.c b/fs/read_write.c
index bcb0ef2..1f8dc37 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -197,13 +197,13 @@
 	struct inode *inode;
 	loff_t pos;
 
+	inode = file->f_path.dentry->d_inode;
 	if (unlikely((ssize_t) count < 0))
 		goto Einval;
 	pos = *ppos;
 	if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
 		goto Einval;
 
-	inode = file->f_path.dentry->d_inode;
 	if (unlikely(inode->i_flock && MANDATORY_LOCK(inode))) {
 		int retval = locks_mandatory_area(
 			read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
index fba304e..f85c5cf 100644
--- a/fs/reiserfs/do_balan.c
+++ b/fs/reiserfs/do_balan.c
@@ -19,6 +19,7 @@
 #include <linux/time.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/buffer_head.h>
+#include <linux/kernel.h>
 
 #ifdef CONFIG_REISERFS_CHECK
 
@@ -1756,7 +1757,7 @@
 	if (buffer_dirty(bh))
 		reiserfs_warning(tb->tb_sb,
 				 "store_thrown deals with dirty buffer");
-	for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(tb->thrown); i++)
 		if (!tb->thrown[i]) {
 			tb->thrown[i] = bh;
 			get_bh(bh);	/* free_thrown puts this */
@@ -1769,7 +1770,7 @@
 {
 	int i;
 	b_blocknr_t blocknr;
-	for (i = 0; i < sizeof(tb->thrown) / sizeof(tb->thrown[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(tb->thrown); i++) {
 		if (tb->thrown[i]) {
 			blocknr = tb->thrown[i]->b_blocknr;
 			if (buffer_dirty(tb->thrown[i]))
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 5109f1d..abfada2 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1556,7 +1556,7 @@
 	.splice_write = generic_file_splice_write,
 };
 
-struct inode_operations reiserfs_file_inode_operations = {
+const struct inode_operations reiserfs_file_inode_operations = {
 	.truncate = reiserfs_vfs_truncate_file,
 	.setattr = reiserfs_setattr,
 	.setxattr = reiserfs_setxattr,
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 23f5cd5..a216184 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1525,7 +1525,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations reiserfs_dir_inode_operations = {
+const struct inode_operations reiserfs_dir_inode_operations = {
 	//&reiserfs_dir_operations,   /* default_file_ops */
 	.create = reiserfs_create,
 	.lookup = reiserfs_lookup,
@@ -1548,7 +1548,7 @@
  * symlink operations.. same as page_symlink_inode_operations, with xattr
  * stuff added
  */
-struct inode_operations reiserfs_symlink_inode_operations = {
+const struct inode_operations reiserfs_symlink_inode_operations = {
 	.readlink = generic_readlink,
 	.follow_link = page_follow_link_light,
 	.put_link = page_put_link,
@@ -1564,7 +1564,7 @@
 /*
  * special file operations.. just xattr/acl stuff
  */
-struct inode_operations reiserfs_special_inode_operations = {
+const struct inode_operations reiserfs_special_inode_operations = {
 	.setattr = reiserfs_setattr,
 	.setxattr = reiserfs_setxattr,
 	.getxattr = reiserfs_getxattr,
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 58ad455..f13a7f1 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -593,7 +593,7 @@
 				   loff_t);
 #endif
 
-static struct super_operations reiserfs_sops = {
+static const struct super_operations reiserfs_sops = {
 	.alloc_inode = reiserfs_alloc_inode,
 	.destroy_inode = reiserfs_destroy_inode,
 	.write_inode = reiserfs_write_inode,
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index d3e243a..fd60101 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -110,7 +110,7 @@
 	return sum;
 }
 
-static struct super_operations romfs_ops;
+static const struct super_operations romfs_ops;
 
 static int romfs_fill_super(struct super_block *s, void *data, int silent)
 {
@@ -468,7 +468,7 @@
 	.readdir	= romfs_readdir,
 };
 
-static struct inode_operations romfs_dir_inode_operations = {
+static const struct inode_operations romfs_dir_inode_operations = {
 	.lookup		= romfs_lookup,
 };
 
@@ -598,7 +598,7 @@
 	return 0;
 }
 
-static struct super_operations romfs_ops = {
+static const struct super_operations romfs_ops = {
 	.alloc_inode	= romfs_alloc_inode,
 	.destroy_inode	= romfs_destroy_inode,
 	.read_inode	= romfs_read_inode,
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index b1e58d1..50136b1 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -42,7 +42,7 @@
 	.open		= smb_dir_open,
 };
 
-struct inode_operations smb_dir_inode_operations =
+const struct inode_operations smb_dir_inode_operations =
 {
 	.create		= smb_create,
 	.lookup		= smb_lookup,
@@ -54,7 +54,7 @@
 	.setattr	= smb_notify_change,
 };
 
-struct inode_operations smb_dir_inode_operations_unix =
+const struct inode_operations smb_dir_inode_operations_unix =
 {
 	.create		= smb_create,
 	.lookup		= smb_lookup,
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index e50533a..f161797 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -418,7 +418,7 @@
 	.sendfile	= smb_file_sendfile,
 };
 
-struct inode_operations smb_file_inode_operations =
+const struct inode_operations smb_file_inode_operations =
 {
 	.permission	= smb_file_permission,
 	.getattr	= smb_getattr,
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 84dfe3f..5faba4f 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -98,7 +98,7 @@
 	return 0;
 }
 
-static struct super_operations smb_sops =
+static const struct super_operations smb_sops =
 {
 	.alloc_inode	= smb_alloc_inode,
 	.destroy_inode	= smb_destroy_inode,
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index 34fb462..03f456c 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -36,8 +36,8 @@
 extern void smb_install_null_ops(struct smb_ops *ops);
 /* dir.c */
 extern const struct file_operations smb_dir_operations;
-extern struct inode_operations smb_dir_inode_operations;
-extern struct inode_operations smb_dir_inode_operations_unix;
+extern const struct inode_operations smb_dir_inode_operations;
+extern const struct inode_operations smb_dir_inode_operations_unix;
 extern void smb_new_dentry(struct dentry *dentry);
 extern void smb_renew_times(struct dentry *dentry);
 /* cache.c */
@@ -65,7 +65,7 @@
 /* file.c */
 extern const struct address_space_operations smb_file_aops;
 extern const struct file_operations smb_file_operations;
-extern struct inode_operations smb_file_inode_operations;
+extern const struct inode_operations smb_file_inode_operations;
 /* ioctl.c */
 extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
 /* smbiod.c */
@@ -84,4 +84,4 @@
 extern int smb_request_recv(struct smb_sb_info *server);
 /* symlink.c */
 extern int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname);
-extern struct inode_operations smb_link_inode_operations;
+extern const struct inode_operations smb_link_inode_operations;
diff --git a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c
index cdc53c4..e4bf345 100644
--- a/fs/smbfs/symlink.c
+++ b/fs/smbfs/symlink.c
@@ -62,7 +62,7 @@
 		__putname(s);
 }
 
-struct inode_operations smb_link_inode_operations =
+const struct inode_operations smb_link_inode_operations =
 {
 	.readlink	= generic_readlink,
 	.follow_link	= smb_follow_link,
diff --git a/fs/super.c b/fs/super.c
index 3e7458c..60b1e50 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -285,7 +285,7 @@
  */
 void generic_shutdown_super(struct super_block *sb)
 {
-	struct super_operations *sop = sb->s_op;
+	const struct super_operations *sop = sb->s_op;
 
 	if (sb->s_root) {
 		shrink_dcache_for_umount(sb);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 9e95e7a..8813990 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -296,7 +296,7 @@
 	return ERR_PTR(err);
 }
 
-struct inode_operations sysfs_dir_inode_operations = {
+const struct inode_operations sysfs_dir_inode_operations = {
 	.lookup		= sysfs_lookup,
 	.setattr	= sysfs_setattr,
 };
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 542d2bc..dd1344b 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -29,7 +29,7 @@
 	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
 };
 
-static struct inode_operations sysfs_inode_operations ={
+static const struct inode_operations sysfs_inode_operations ={
 	.setattr	= sysfs_setattr,
 };
 
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index f6a87a8..23a48a3 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -21,7 +21,7 @@
 
 static void sysfs_clear_inode(struct inode *inode);
 
-static struct super_operations sysfs_ops = {
+static const struct super_operations sysfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= sysfs_delete_inode,
 	.clear_inode	= sysfs_clear_inode,
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 4869f61..7b9c5bf 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -181,7 +181,7 @@
 		free_page((unsigned long)page);
 }
 
-struct inode_operations sysfs_symlink_inode_operations = {
+const struct inode_operations sysfs_symlink_inode_operations = {
 	.readlink = generic_readlink,
 	.follow_link = sysfs_follow_link,
 	.put_link = sysfs_put_link,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index fe1cbfd..d976b00 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -26,8 +26,8 @@
 extern const struct file_operations sysfs_dir_operations;
 extern const struct file_operations sysfs_file_operations;
 extern const struct file_operations bin_fops;
-extern struct inode_operations sysfs_dir_inode_operations;
-extern struct inode_operations sysfs_symlink_inode_operations;
+extern const struct inode_operations sysfs_dir_inode_operations;
+extern const struct inode_operations sysfs_symlink_inode_operations;
 
 struct sysfs_symlink {
 	char * link_name;
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 47a4b72..0732ddb 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -30,7 +30,7 @@
 	.sendfile	= generic_file_sendfile,
 };
 
-struct inode_operations sysv_file_inode_operations = {
+const struct inode_operations sysv_file_inode_operations = {
 	.truncate	= sysv_truncate,
 	.getattr	= sysv_getattr,
 };
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index ead9864..9311cac 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -142,7 +142,7 @@
 	}
 }
 
-static struct inode_operations sysv_symlink_inode_operations = {
+static const struct inode_operations sysv_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -327,7 +327,7 @@
 		inode_init_once(&si->vfs_inode);
 }
 
-struct super_operations sysv_sops = {
+const struct super_operations sysv_sops = {
 	.alloc_inode	= sysv_alloc_inode,
 	.destroy_inode	= sysv_destroy_inode,
 	.read_inode	= sysv_read_inode,
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index f7c08db..4e48abb 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -292,7 +292,7 @@
 /*
  * directories can handle most operations...
  */
-struct inode_operations sysv_dir_inode_operations = {
+const struct inode_operations sysv_dir_inode_operations = {
 	.create		= sysv_create,
 	.lookup		= sysv_lookup,
 	.link		= sysv_link,
diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c
index b85ce61..00d2f8a 100644
--- a/fs/sysv/symlink.c
+++ b/fs/sysv/symlink.c
@@ -14,7 +14,7 @@
 	return NULL;
 }
 
-struct inode_operations sysv_fast_symlink_inode_operations = {
+const struct inode_operations sysv_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= sysv_follow_link,
 };
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index dcb18b2..5b4fedf 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -159,13 +159,13 @@
 extern ino_t sysv_inode_by_name(struct dentry *);
 
 
-extern struct inode_operations sysv_file_inode_operations;
-extern struct inode_operations sysv_dir_inode_operations;
-extern struct inode_operations sysv_fast_symlink_inode_operations;
+extern const struct inode_operations sysv_file_inode_operations;
+extern const struct inode_operations sysv_dir_inode_operations;
+extern const struct inode_operations sysv_fast_symlink_inode_operations;
 extern const struct file_operations sysv_file_operations;
 extern const struct file_operations sysv_dir_operations;
 extern const struct address_space_operations sysv_aops;
-extern struct super_operations sysv_sops;
+extern const struct super_operations sysv_sops;
 extern struct dentry_operations sysv_dentry_operations;
 
 
diff --git a/fs/udf/file.c b/fs/udf/file.c
index d81f2db..40d5047 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -263,6 +263,6 @@
 	.sendfile		= generic_file_sendfile,
 };
 
-struct inode_operations udf_file_inode_operations = {
+const struct inode_operations udf_file_inode_operations = {
 	.truncate		= udf_truncate,
 };
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 7316332..fe361cd 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1308,7 +1308,7 @@
 	return retval;
 }
 
-struct inode_operations udf_dir_inode_operations = {
+const struct inode_operations udf_dir_inode_operations = {
 	.lookup				= udf_lookup,
 	.create				= udf_create,
 	.link				= udf_link,
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 1dbc295..8672b88 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -160,7 +160,7 @@
 }
 
 /* Superblock operations */
-static struct super_operations udf_sb_ops = {
+static const struct super_operations udf_sb_ops = {
 	.alloc_inode		= udf_alloc_inode,
 	.destroy_inode		= udf_destroy_inode,
 	.write_inode		= udf_write_inode,
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 1033b7c..ee1dece 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -42,9 +42,9 @@
 struct buffer_head;
 struct super_block;
 
-extern struct inode_operations udf_dir_inode_operations;
+extern const struct inode_operations udf_dir_inode_operations;
 extern const struct file_operations udf_dir_operations;
-extern struct inode_operations udf_file_inode_operations;
+extern const struct inode_operations udf_file_inode_operations;
 extern const struct file_operations udf_file_operations;
 extern const struct address_space_operations udf_aops;
 extern const struct address_space_operations udf_adinicb_aops;
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 638f4c5..0e97a4f 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -4,6 +4,8 @@
  * Copyright (C) 1998
  * Daniel Pirkl <daniel.pirkl@email.cz>
  * Charles University, Faculty of Mathematics and Physics
+ *
+ * UFS2 write support Evgeniy Dushistov <dushistov@mail.ru>, 2007
  */
 
 #include <linux/fs.h>
@@ -21,38 +23,42 @@
 #include "swab.h"
 #include "util.h"
 
-static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
-static unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
+#define INVBLOCK ((u64)-1L)
+
+static u64 ufs_add_fragments(struct inode *, u64, unsigned, unsigned, int *);
+static u64 ufs_alloc_fragments(struct inode *, unsigned, u64, unsigned, int *);
+static u64 ufs_alloccg_block(struct inode *, struct ufs_cg_private_info *, u64, int *);
+static u64 ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, u64, unsigned);
 static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
 static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
 
 /*
  * Free 'count' fragments from fragment number 'fragment'
  */
-void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
+void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
-	unsigned cgno, bit, end_bit, bbase, blkmap, i, blkno, cylno;
+	unsigned cgno, bit, end_bit, bbase, blkmap, i;
+	u64 blkno;
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first(uspi);
 	
-	UFSD("ENTER, fragment %u, count %u\n", fragment, count);
+	UFSD("ENTER, fragment %llu, count %u\n",
+	     (unsigned long long)fragment, count);
 	
 	if (ufs_fragnum(fragment) + count > uspi->s_fpg)
 		ufs_error (sb, "ufs_free_fragments", "internal error");
 	
 	lock_super(sb);
 	
-	cgno = ufs_dtog(fragment);
-	bit = ufs_dtogd(fragment);
+	cgno = ufs_dtog(uspi, fragment);
+	bit = ufs_dtogd(uspi, fragment);
 	if (cgno >= uspi->s_ncg) {
 		ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");
 		goto failed;
@@ -101,9 +107,13 @@
 		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
 		uspi->cs_total.cs_nbfree++;
 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
-		cylno = ufs_cbtocylno (bbase);
-		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1);
-		fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+		if (uspi->fs_magic != UFS2_MAGIC) {
+			unsigned cylno = ufs_cbtocylno (bbase);
+
+			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
+						  ufs_cbtorpos(bbase)), 1);
+			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+		}
 	}
 	
 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
@@ -127,24 +137,27 @@
 /*
  * Free 'count' fragments from fragment number 'fragment' (free whole blocks)
  */
-void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
+void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
-	unsigned overflow, cgno, bit, end_bit, blkno, i, cylno;
+	unsigned overflow, cgno, bit, end_bit, i;
+	u64 blkno;
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first(uspi);
 
-	UFSD("ENTER, fragment %u, count %u\n", fragment, count);
+	UFSD("ENTER, fragment %llu, count %u\n",
+	     (unsigned long long)fragment, count);
 	
 	if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
 		ufs_error (sb, "ufs_free_blocks", "internal error, "
-			"fragment %u, count %u\n", fragment, count);
+			   "fragment %llu, count %u\n",
+			   (unsigned long long)fragment, count);
 		goto failed;
 	}
 
@@ -152,8 +165,8 @@
 	
 do_more:
 	overflow = 0;
-	cgno = ufs_dtog (fragment);
-	bit = ufs_dtogd (fragment);
+	cgno = ufs_dtog(uspi, fragment);
+	bit = ufs_dtogd(uspi, fragment);
 	if (cgno >= uspi->s_ncg) {
 		ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
 		goto failed_unlock;
@@ -187,9 +200,14 @@
 		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
 		uspi->cs_total.cs_nbfree++;
 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
-		cylno = ufs_cbtocylno(i);
-		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1);
-		fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+
+		if (uspi->fs_magic != UFS2_MAGIC) {
+			unsigned cylno = ufs_cbtocylno(i);
+
+			fs16_add(sb, &ubh_cg_blks(ucpi, cylno,
+						  ufs_cbtorpos(i)), 1);
+			fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+		}
 	}
 
 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
@@ -308,15 +326,19 @@
 	}
 }
 
-unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
-			   unsigned goal, unsigned count, int * err, struct page *locked_page)
+u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
+			   u64 goal, unsigned count, int *err,
+			   struct page *locked_page)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
-	unsigned cgno, oldcount, newcount, tmp, request, result;
+	unsigned cgno, oldcount, newcount;
+	u64 tmp, request, result;
 	
-	UFSD("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count);
+	UFSD("ENTER, ino %lu, fragment %llu, goal %llu, count %u\n",
+	     inode->i_ino, (unsigned long long)fragment,
+	     (unsigned long long)goal, count);
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -324,11 +346,12 @@
 	*err = -ENOSPC;
 
 	lock_super (sb);
-	
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
+
 	if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
-		ufs_warning (sb, "ufs_new_fragments", "internal warning"
-			" fragment %u, count %u", fragment, count);
+		ufs_warning(sb, "ufs_new_fragments", "internal warning"
+			    " fragment %llu, count %u",
+			    (unsigned long long)fragment, count);
 		count = uspi->s_fpb - ufs_fragnum(fragment); 
 	}
 	oldcount = ufs_fragnum (fragment);
@@ -339,10 +362,12 @@
 	 */
 	if (oldcount) {
 		if (!tmp) {
-			ufs_error (sb, "ufs_new_fragments", "internal error, "
-				"fragment %u, tmp %u\n", fragment, tmp);
-			unlock_super (sb);
-			return (unsigned)-1;
+			ufs_error(sb, "ufs_new_fragments", "internal error, "
+				  "fragment %llu, tmp %llu\n",
+				  (unsigned long long)fragment,
+				  (unsigned long long)tmp);
+			unlock_super(sb);
+			return INVBLOCK;
 		}
 		if (fragment < UFS_I(inode)->i_lastfrag) {
 			UFSD("EXIT (ALREADY ALLOCATED)\n");
@@ -372,7 +397,7 @@
 	if (goal == 0) 
 		cgno = ufs_inotocg (inode->i_ino);
 	else
-		cgno = ufs_dtog (goal);
+		cgno = ufs_dtog(uspi, goal);
 	 
 	/*
 	 * allocate new fragment
@@ -380,14 +405,16 @@
 	if (oldcount == 0) {
 		result = ufs_alloc_fragments (inode, cgno, goal, count, err);
 		if (result) {
-			*p = cpu_to_fs32(sb, result);
+			ufs_cpu_to_data_ptr(sb, p, result);
 			*err = 0;
-			UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
-			ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
-					locked_page != NULL);
+			UFS_I(inode)->i_lastfrag =
+				max_t(u32, UFS_I(inode)->i_lastfrag,
+				      fragment + count);
+			ufs_clear_frags(inode, result + oldcount,
+					newcount - oldcount, locked_page != NULL);
 		}
 		unlock_super(sb);
-		UFSD("EXIT, result %u\n", result);
+		UFSD("EXIT, result %llu\n", (unsigned long long)result);
 		return result;
 	}
 
@@ -401,7 +428,7 @@
 		ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
 				locked_page != NULL);
 		unlock_super(sb);
-		UFSD("EXIT, result %u\n", result);
+		UFSD("EXIT, result %llu\n", (unsigned long long)result);
 		return result;
 	}
 
@@ -433,15 +460,14 @@
 				locked_page != NULL);
 		ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
 				   result, locked_page);
-
-		*p = cpu_to_fs32(sb, result);
+		ufs_cpu_to_data_ptr(sb, p, result);
 		*err = 0;
 		UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
 		unlock_super(sb);
 		if (newcount < request)
 			ufs_free_fragments (inode, result + newcount, request - newcount);
 		ufs_free_fragments (inode, tmp, oldcount);
-		UFSD("EXIT, result %u\n", result);
+		UFSD("EXIT, result %llu\n", (unsigned long long)result);
 		return result;
 	}
 
@@ -450,9 +476,8 @@
 	return 0;
 }		
 
-static unsigned
-ufs_add_fragments (struct inode * inode, unsigned fragment,
-		   unsigned oldcount, unsigned newcount, int * err)
+static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
+			     unsigned oldcount, unsigned newcount, int *err)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
@@ -461,14 +486,15 @@
 	struct ufs_cylinder_group * ucg;
 	unsigned cgno, fragno, fragoff, count, fragsize, i;
 	
-	UFSD("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount);
+	UFSD("ENTER, fragment %llu, oldcount %u, newcount %u\n",
+	     (unsigned long long)fragment, oldcount, newcount);
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first (uspi);
 	count = newcount - oldcount;
 	
-	cgno = ufs_dtog(fragment);
+	cgno = ufs_dtog(uspi, fragment);
 	if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
 		return 0;
 	if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
@@ -483,7 +509,7 @@
 		return 0;
 	}
 
-	fragno = ufs_dtogd (fragment);
+	fragno = ufs_dtogd(uspi, fragment);
 	fragoff = ufs_fragnum (fragno);
 	for (i = oldcount; i < newcount; i++)
 		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
@@ -521,7 +547,7 @@
 	}
 	sb->s_dirt = 1;
 
-	UFSD("EXIT, fragment %u\n", fragment);
+	UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment);
 	
 	return fragment;
 }
@@ -534,17 +560,19 @@
 		if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
 			goto cg_found; 
 
-static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
-	unsigned goal, unsigned count, int * err)
+static u64 ufs_alloc_fragments(struct inode *inode, unsigned cgno,
+			       u64 goal, unsigned count, int *err)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_cg_private_info * ucpi;
 	struct ufs_cylinder_group * ucg;
-	unsigned oldcg, i, j, k, result, allocsize;
+	unsigned oldcg, i, j, k, allocsize;
+	u64 result;
 	
-	UFSD("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count);
+	UFSD("ENTER, ino %lu, cgno %u, goal %llu, count %u\n",
+	     inode->i_ino, cgno, (unsigned long long)goal, count);
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -593,7 +621,7 @@
 
 	if (count == uspi->s_fpb) {
 		result = ufs_alloccg_block (inode, ucpi, goal, err);
-		if (result == (unsigned)-1)
+		if (result == INVBLOCK)
 			return 0;
 		goto succed;
 	}
@@ -604,9 +632,9 @@
 	
 	if (allocsize == uspi->s_fpb) {
 		result = ufs_alloccg_block (inode, ucpi, goal, err);
-		if (result == (unsigned)-1)
+		if (result == INVBLOCK)
 			return 0;
-		goal = ufs_dtogd (result);
+		goal = ufs_dtogd(uspi, result);
 		for (i = count; i < uspi->s_fpb; i++)
 			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
 		i = uspi->s_fpb - count;
@@ -620,7 +648,7 @@
 	}
 
 	result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
-	if (result == (unsigned)-1)
+	if (result == INVBLOCK)
 		return 0;
 	if(DQUOT_ALLOC_BLOCK(inode, count)) {
 		*err = -EDQUOT;
@@ -647,20 +675,21 @@
 	sb->s_dirt = 1;
 
 	result += cgno * uspi->s_fpg;
-	UFSD("EXIT3, result %u\n", result);
+	UFSD("EXIT3, result %llu\n", (unsigned long long)result);
 	return result;
 }
 
-static unsigned ufs_alloccg_block (struct inode * inode,
-	struct ufs_cg_private_info * ucpi, unsigned goal, int * err)
+static u64 ufs_alloccg_block(struct inode *inode,
+			     struct ufs_cg_private_info *ucpi,
+			     u64 goal, int *err)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_cylinder_group * ucg;
-	unsigned result, cylno, blkno;
+	u64 result, blkno;
 
-	UFSD("ENTER, goal %u\n", goal);
+	UFSD("ENTER, goal %llu\n", (unsigned long long)goal);
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -672,7 +701,7 @@
 		goto norot;
 	}
 	goal = ufs_blknum (goal);
-	goal = ufs_dtogd (goal);
+	goal = ufs_dtogd(uspi, goal);
 	
 	/*
 	 * If the requested block is available, use it.
@@ -684,8 +713,8 @@
 	
 norot:	
 	result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb);
-	if (result == (unsigned)-1)
-		return (unsigned)-1;
+	if (result == INVBLOCK)
+		return INVBLOCK;
 	ucpi->c_rotor = result;
 gotit:
 	blkno = ufs_fragstoblks(result);
@@ -694,17 +723,22 @@
 		ufs_clusteracct (sb, ucpi, blkno, -1);
 	if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) {
 		*err = -EDQUOT;
-		return (unsigned)-1;
+		return INVBLOCK;
 	}
 
 	fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
 	uspi->cs_total.cs_nbfree--;
 	fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
-	cylno = ufs_cbtocylno(result);
-	fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1);
-	fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+
+	if (uspi->fs_magic != UFS2_MAGIC) {
+		unsigned cylno = ufs_cbtocylno((unsigned)result);
+
+		fs16_sub(sb, &ubh_cg_blks(ucpi, cylno,
+					  ufs_cbtorpos((unsigned)result)), 1);
+		fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
+	}
 	
-	UFSD("EXIT, result %u\n", result);
+	UFSD("EXIT, result %llu\n", (unsigned long long)result);
 
 	return result;
 }
@@ -744,9 +778,9 @@
  * @goal: near which block we want find new one
  * @count: specified size
  */
-static unsigned ufs_bitmap_search(struct super_block *sb,
-				  struct ufs_cg_private_info *ucpi,
-				  unsigned goal, unsigned count)
+static u64 ufs_bitmap_search(struct super_block *sb,
+			     struct ufs_cg_private_info *ucpi,
+			     u64 goal, unsigned count)
 {
 	/*
 	 * Bit patterns for identifying fragments in the block map
@@ -761,16 +795,18 @@
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct ufs_super_block_first *usb1;
 	struct ufs_cylinder_group *ucg;
-	unsigned start, length, loc, result;
+	unsigned start, length, loc;
 	unsigned pos, want, blockmap, mask, end;
+	u64 result;
 
-	UFSD("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count);
+	UFSD("ENTER, cg %u, goal %llu, count %u\n", ucpi->c_cgx,
+	     (unsigned long long)goal, count);
 
 	usb1 = ubh_get_usb_first (uspi);
 	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 
 	if (goal)
-		start = ufs_dtogd(goal) >> 3;
+		start = ufs_dtogd(uspi, goal) >> 3;
 	else
 		start = ucpi->c_frotor >> 3;
 		
@@ -790,7 +826,7 @@
 				  " length %u, count %u, freeoff %u\n",
 				  ucpi->c_cgx, start, length, count,
 				  ucpi->c_freeoff);
-			return (unsigned)-1;
+			return INVBLOCK;
 		}
 		start = 0;
 	}
@@ -808,7 +844,8 @@
 		want = want_arr[count];
 		for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
 			if ((blockmap & mask) == want) {
-				UFSD("EXIT, result %u\n", result);
+				UFSD("EXIT, result %llu\n",
+				     (unsigned long long)result);
 				return result + pos;
  			}
 			mask <<= 1;
@@ -819,7 +856,7 @@
 	ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
 		  ucpi->c_cgx);
 	UFSD("EXIT (FAILED)\n");
-	return (unsigned)-1;
+	return INVBLOCK;
 }
 
 static void ufs_clusteracct(struct super_block * sb,
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 2ad1259..b868878 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -18,6 +18,9 @@
  *  Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
+ *
+ * UFS2 write support added by
+ * Evgeniy Dushistov <dushistov@mail.ru>, 2007
  */
 
 #include <linux/fs.h>
@@ -126,6 +129,47 @@
 }
 
 /*
+ * Nullify new chunk of inodes,
+ * BSD people also set ui_gen field of inode
+ * during nullification, but we not care about
+ * that because of linux ufs do not support NFS
+ */
+static void ufs2_init_inodes_chunk(struct super_block *sb,
+				   struct ufs_cg_private_info *ucpi,
+				   struct ufs_cylinder_group *ucg)
+{
+	struct buffer_head *bh;
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+	sector_t beg = uspi->s_sbbase +
+		ufs_inotofsba(ucpi->c_cgx * uspi->s_ipg +
+			      fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk));
+	sector_t end = beg + uspi->s_fpb;
+
+	UFSD("ENTER cgno %d\n", ucpi->c_cgx);
+
+	for (; beg < end; ++beg) {
+		bh = sb_getblk(sb, beg);
+		lock_buffer(bh);
+		memset(bh->b_data, 0, sb->s_blocksize);
+		set_buffer_uptodate(bh);
+		mark_buffer_dirty(bh);
+		unlock_buffer(bh);
+		if (sb->s_flags & MS_SYNCHRONOUS)
+			sync_dirty_buffer(bh);
+		brelse(bh);
+	}
+
+	fs32_add(sb, &ucg->cg_u.cg_u2.cg_initediblk, uspi->s_inopb);
+	ubh_mark_buffer_dirty(UCPI_UBH(ucpi));
+	if (sb->s_flags & MS_SYNCHRONOUS) {
+		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
+		ubh_wait_on_buffer(UCPI_UBH(ucpi));
+	}
+
+	UFSD("EXIT\n");
+}
+
+/*
  * There are two policies for allocating an inode.  If the new inode is
  * a directory, then a forward search is made for a block group with both
  * free space and a low directory-to-inode ratio; if that fails, then of
@@ -146,6 +190,7 @@
 	struct inode * inode;
 	unsigned cg, bit, i, j, start;
 	struct ufs_inode_info *ufsi;
+	int err = -ENOSPC;
 
 	UFSD("ENTER\n");
 	
@@ -198,13 +243,15 @@
 			goto cg_found;
 		}
 	}
-	
+
 	goto failed;
 
 cg_found:
 	ucpi = ufs_load_cylinder (sb, cg);
-	if (!ucpi)
+	if (!ucpi) {
+		err = -EIO;
 		goto failed;
+	}
 	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 	if (!ufs_cg_chkmagic(sb, ucg)) 
 		ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");
@@ -216,6 +263,7 @@
 		if (!(bit < start)) {
 			ufs_error (sb, "ufs_new_inode",
 			    "cylinder group %u corrupted - error in inode bitmap\n", cg);
+			err = -EIO;
 			goto failed;
 		}
 	}
@@ -224,9 +272,18 @@
 		ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
 	else {
 		ufs_panic (sb, "ufs_new_inode", "internal error");
+		err = -EIO;
 		goto failed;
 	}
-	
+
+	if (uspi->fs_magic == UFS2_MAGIC) {
+		u32 initediblk = fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_initediblk);
+
+		if (bit + uspi->s_inopb > initediblk &&
+		    initediblk < fs32_to_cpu(sb, ucg->cg_u.cg_u2.cg_niblk))
+			ufs2_init_inodes_chunk(sb, ucpi, ucg);
+	}
+
 	fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1);
 	uspi->cs_total.cs_nifree--;
 	fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1);
@@ -236,7 +293,6 @@
 		uspi->cs_total.cs_ndir++;
 		fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1);
 	}
-
 	ubh_mark_buffer_dirty (USPI_UBH(uspi));
 	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
 	if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -245,6 +301,7 @@
 	}
 	sb->s_dirt = 1;
 
+	inode->i_ino = cg * uspi->s_ipg + bit;
 	inode->i_mode = mode;
 	inode->i_uid = current->fsuid;
 	if (dir->i_mode & S_ISGID) {
@@ -254,39 +311,72 @@
 	} else
 		inode->i_gid = current->fsgid;
 
-	inode->i_ino = cg * uspi->s_ipg + bit;
 	inode->i_blocks = 0;
+	inode->i_generation = 0;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 	ufsi->i_flags = UFS_I(dir)->i_flags;
 	ufsi->i_lastfrag = 0;
-	ufsi->i_gen = 0;
 	ufsi->i_shadow = 0;
 	ufsi->i_osync = 0;
 	ufsi->i_oeftflag = 0;
 	ufsi->i_dir_start_lookup = 0;
 	memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
-
 	insert_inode_hash(inode);
 	mark_inode_dirty(inode);
 
+	if (uspi->fs_magic == UFS2_MAGIC) {
+		struct buffer_head *bh;
+		struct ufs2_inode *ufs2_inode;
+
+		/*
+		 * setup birth date, we do it here because of there is no sense
+		 * to hold it in struct ufs_inode_info, and lose 64 bit
+		 */
+		bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
+		if (!bh) {
+			ufs_warning(sb, "ufs_read_inode",
+				    "unable to read inode %lu\n",
+				    inode->i_ino);
+			err = -EIO;
+			goto fail_remove_inode;
+		}
+		lock_buffer(bh);
+		ufs2_inode = (struct ufs2_inode *)bh->b_data;
+		ufs2_inode += ufs_inotofsbo(inode->i_ino);
+		ufs2_inode->ui_birthtime.tv_sec =
+			cpu_to_fs32(sb, CURRENT_TIME_SEC.tv_sec);
+		ufs2_inode->ui_birthtime.tv_usec = 0;
+		mark_buffer_dirty(bh);
+		unlock_buffer(bh);
+		if (sb->s_flags & MS_SYNCHRONOUS)
+			sync_dirty_buffer(bh);
+		brelse(bh);
+	}
+
 	unlock_super (sb);
 
 	if (DQUOT_ALLOC_INODE(inode)) {
 		DQUOT_DROP(inode);
-		inode->i_flags |= S_NOQUOTA;
-		inode->i_nlink = 0;
-		iput(inode);
-		return ERR_PTR(-EDQUOT);
+		err = -EDQUOT;
+		goto fail_without_unlock;
 	}
 
 	UFSD("allocating inode %lu\n", inode->i_ino);
 	UFSD("EXIT\n");
 	return inode;
 
+fail_remove_inode:
+	unlock_super(sb);
+fail_without_unlock:
+	inode->i_flags |= S_NOQUOTA;
+	inode->i_nlink = 0;
+	iput(inode);
+	UFSD("EXIT (FAILED): err %d\n", err);
+	return ERR_PTR(err);
 failed:
 	unlock_super (sb);
 	make_bad_inode(inode);
 	iput (inode);
-	UFSD("EXIT (FAILED)\n");
-	return ERR_PTR(-ENOSPC);
+	UFSD("EXIT (FAILED): err %d\n", err);
+	return ERR_PTR(err);
 }
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 4295ca9..fb34ad0 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -170,7 +170,7 @@
  * @locked_page - for ufs_new_fragments()
  */
 static struct buffer_head *
-ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
+ufs_inode_getfrag(struct inode *inode, u64 fragment,
 		  sector_t new_fragment, unsigned int required, int *err,
 		  long *phys, int *new, struct page *locked_page)
 {
@@ -178,12 +178,12 @@
 	struct super_block *sb = inode->i_sb;
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct buffer_head * result;
-	unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
-	unsigned tmp, goal;
-	__fs32 * p, * p2;
+	unsigned blockoff, lastblockoff;
+	u64 tmp, goal, lastfrag, block, lastblock;
+	void *p, *p2;
 
-	UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, "
-	     "metadata %d\n", inode->i_ino, fragment,
+	UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, required %u, "
+	     "metadata %d\n", inode->i_ino, (unsigned long long)fragment,
 	     (unsigned long long)new_fragment, required, !phys);
 
         /* TODO : to be done for write support
@@ -193,17 +193,20 @@
 
 	block = ufs_fragstoblks (fragment);
 	blockoff = ufs_fragnum (fragment);
-	p = ufsi->i_u1.i_data + block;
+	p = ufs_get_direct_data_ptr(uspi, ufsi, block);
+
 	goal = 0;
 
 repeat:
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
+
 	lastfrag = ufsi->i_lastfrag;
 	if (tmp && fragment < lastfrag) {
 		if (!phys) {
 			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
-			if (tmp == fs32_to_cpu(sb, *p)) {
-				UFSD("EXIT, result %u\n", tmp + blockoff);
+			if (tmp == ufs_data_ptr_to_cpu(sb, p)) {
+				UFSD("EXIT, result %llu\n",
+				     (unsigned long long)tmp + blockoff);
 				return result;
 			}
 			brelse (result);
@@ -224,10 +227,11 @@
 		 * We must reallocate last allocated block
 		 */
 		if (lastblockoff) {
-			p2 = ufsi->i_u1.i_data + lastblock;
-			tmp = ufs_new_fragments (inode, p2, lastfrag, 
-						 fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff,
-						 err, locked_page);
+			p2 = ufs_get_direct_data_ptr(uspi, ufsi, lastblock);
+			tmp = ufs_new_fragments(inode, p2, lastfrag,
+						ufs_data_ptr_to_cpu(sb, p2),
+						uspi->s_fpb - lastblockoff,
+						err, locked_page);
 			if (!tmp) {
 				if (lastfrag != ufsi->i_lastfrag)
 					goto repeat;
@@ -237,27 +241,31 @@
 			lastfrag = ufsi->i_lastfrag;
 			
 		}
-		tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]);
+		tmp = ufs_data_ptr_to_cpu(sb,
+					 ufs_get_direct_data_ptr(uspi, ufsi,
+								 lastblock));
 		if (tmp)
 			goal = tmp + uspi->s_fpb;
 		tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
 					 goal, required + blockoff,
 					 err,
 					 phys != NULL ? locked_page : NULL);
-	}
+	} else if (lastblock == block) {
 	/*
 	 * We will extend last allocated block
 	 */
-	else if (lastblock == block) {
-		tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
-					fs32_to_cpu(sb, *p), required +  (blockoff - lastblockoff),
+		tmp = ufs_new_fragments(inode, p, fragment -
+					(blockoff - lastblockoff),
+					ufs_data_ptr_to_cpu(sb, p),
+					required +  (blockoff - lastblockoff),
 					err, phys != NULL ? locked_page : NULL);
 	} else /* (lastblock > block) */ {
 	/*
 	 * We will allocate new block before last allocated block
 	 */
 		if (block) {
-			tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[block-1]);
+			tmp = ufs_data_ptr_to_cpu(sb,
+						 ufs_get_direct_data_ptr(uspi, ufsi, block - 1));
 			if (tmp)
 				goal = tmp + uspi->s_fpb;
 		}
@@ -266,7 +274,7 @@
 					phys != NULL ? locked_page : NULL);
 	}
 	if (!tmp) {
-		if ((!blockoff && *p) || 
+		if ((!blockoff && ufs_data_ptr_to_cpu(sb, p)) ||
 		    (blockoff && lastfrag != ufsi->i_lastfrag))
 			goto repeat;
 		*err = -ENOSPC;
@@ -286,7 +294,7 @@
 	if (IS_SYNC(inode))
 		ufs_sync_inode (inode);
 	mark_inode_dirty(inode);
-	UFSD("EXIT, result %u\n", tmp + blockoff);
+	UFSD("EXIT, result %llu\n", (unsigned long long)tmp + blockoff);
 	return result;
 
      /* This part : To be implemented ....
@@ -320,20 +328,22 @@
  */
 static struct buffer_head *
 ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
-		  unsigned int fragment, sector_t new_fragment, int *err,
+		  u64 fragment, sector_t new_fragment, int *err,
 		  long *phys, int *new, struct page *locked_page)
 {
 	struct super_block *sb = inode->i_sb;
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct buffer_head * result;
-	unsigned tmp, goal, block, blockoff;
-	__fs32 * p;
+	unsigned blockoff;
+	u64 tmp, goal, block;
+	void *p;
 
 	block = ufs_fragstoblks (fragment);
 	blockoff = ufs_fragnum (fragment);
 
-	UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n",
-	     inode->i_ino, fragment, (unsigned long long)new_fragment, !phys);
+	UFSD("ENTER, ino %lu, fragment %llu, new_fragment %llu, metadata %d\n",
+	     inode->i_ino, (unsigned long long)fragment,
+	     (unsigned long long)new_fragment, !phys);
 
 	result = NULL;
 	if (!bh)
@@ -344,14 +354,16 @@
 		if (!buffer_uptodate(bh))
 			goto out;
 	}
-
-	p = (__fs32 *) bh->b_data + block;
+	if (uspi->fs_magic == UFS2_MAGIC)
+		p = (__fs64 *)bh->b_data + block;
+	else
+		p = (__fs32 *)bh->b_data + block;
 repeat:
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (tmp) {
 		if (!phys) {
 			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
-			if (tmp == fs32_to_cpu(sb, *p))
+			if (tmp == ufs_data_ptr_to_cpu(sb, p))
 				goto out;
 			brelse (result);
 			goto repeat;
@@ -361,14 +373,16 @@
 		}
 	}
 
-	if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1])))
+	if (block && (uspi->fs_magic == UFS2_MAGIC ?
+		      (tmp = fs64_to_cpu(sb, ((__fs64 *)bh->b_data)[block-1])) :
+		      (tmp = fs32_to_cpu(sb, ((__fs32 *)bh->b_data)[block-1]))))
 		goal = tmp + uspi->s_fpb;
 	else
 		goal = bh->b_blocknr + uspi->s_fpb;
 	tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal,
 				uspi->s_fpb, err, locked_page);
 	if (!tmp) {
-		if (fs32_to_cpu(sb, *p))
+		if (ufs_data_ptr_to_cpu(sb, p))
 			goto repeat;
 		goto out;
 	}		
@@ -386,7 +400,7 @@
 		sync_dirty_buffer(bh);
 	inode->i_ctime = CURRENT_TIME_SEC;
 	mark_inode_dirty(inode);
-	UFSD("result %u\n", tmp + blockoff);
+	UFSD("result %llu\n", (unsigned long long)tmp + blockoff);
 out:
 	brelse (bh);
 	UFSD("EXIT\n");
@@ -616,8 +630,8 @@
 	inode->i_atime.tv_nsec = 0;
 	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
+	inode->i_generation = fs32_to_cpu(sb, ufs_inode->ui_gen);
 	ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
-	ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen);
 	ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
 	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
 
@@ -661,8 +675,8 @@
 	inode->i_atime.tv_nsec = 0;
 	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
+	inode->i_generation = fs32_to_cpu(sb, ufs2_inode->ui_gen);
 	ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
-	ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen);
 	/*
 	ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
 	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
@@ -731,34 +745,11 @@
 	make_bad_inode(inode);
 }
 
-static int ufs_update_inode(struct inode * inode, int do_sync)
+static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode)
 {
-	struct ufs_inode_info *ufsi = UFS_I(inode);
-	struct super_block * sb;
-	struct ufs_sb_private_info * uspi;
-	struct buffer_head * bh;
-	struct ufs_inode * ufs_inode;
-	unsigned i;
-	unsigned flags;
-
-	UFSD("ENTER, ino %lu\n", inode->i_ino);
-
-	sb = inode->i_sb;
-	uspi = UFS_SB(sb)->s_uspi;
-	flags = UFS_SB(sb)->s_flags;
-
-	if (inode->i_ino < UFS_ROOTINO || 
-	    inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
-		ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
-		return -1;
-	}
-
-	bh = sb_bread(sb, ufs_inotofsba(inode->i_ino));
-	if (!bh) {
-		ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
-		return -1;
-	}
-	ufs_inode = (struct ufs_inode *) (bh->b_data + ufs_inotofsbo(inode->i_ino) * sizeof(struct ufs_inode));
+	struct super_block *sb = inode->i_sb;
+ 	struct ufs_inode_info *ufsi = UFS_I(inode);
+ 	unsigned i;
 
 	ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
 	ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
@@ -775,9 +766,9 @@
 	ufs_inode->ui_mtime.tv_usec = 0;
 	ufs_inode->ui_blocks = cpu_to_fs32(sb, inode->i_blocks);
 	ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
-	ufs_inode->ui_gen = cpu_to_fs32(sb, ufsi->i_gen);
+	ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
 
-	if ((flags & UFS_UID_MASK) == UFS_UID_EFT) {
+	if ((UFS_SB(sb)->s_flags & UFS_UID_MASK) == UFS_UID_EFT) {
 		ufs_inode->ui_u3.ui_sun.ui_shadow = cpu_to_fs32(sb, ufsi->i_shadow);
 		ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag);
 	}
@@ -796,6 +787,78 @@
 
 	if (!inode->i_nlink)
 		memset (ufs_inode, 0, sizeof(struct ufs_inode));
+}
+
+static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode)
+{
+	struct super_block *sb = inode->i_sb;
+ 	struct ufs_inode_info *ufsi = UFS_I(inode);
+ 	unsigned i;
+
+	UFSD("ENTER\n");
+	ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode);
+	ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink);
+
+	ufs_inode->ui_uid = cpu_to_fs32(sb, inode->i_uid);
+	ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid);
+
+	ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size);
+	ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec);
+	ufs_inode->ui_atime.tv_usec = 0;
+	ufs_inode->ui_ctime.tv_sec = cpu_to_fs32(sb, inode->i_ctime.tv_sec);
+	ufs_inode->ui_ctime.tv_usec = 0;
+	ufs_inode->ui_mtime.tv_sec = cpu_to_fs32(sb, inode->i_mtime.tv_sec);
+	ufs_inode->ui_mtime.tv_usec = 0;
+
+	ufs_inode->ui_blocks = cpu_to_fs64(sb, inode->i_blocks);
+	ufs_inode->ui_flags = cpu_to_fs32(sb, ufsi->i_flags);
+	ufs_inode->ui_gen = cpu_to_fs32(sb, inode->i_generation);
+
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+		/* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */
+		ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.u2_i_data[0];
+	} else if (inode->i_blocks) {
+		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
+			ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.u2_i_data[i];
+	} else {
+		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
+			ufs_inode->ui_u2.ui_symlink[i] = ufsi->i_u1.i_symlink[i];
+ 	}
+
+	if (!inode->i_nlink)
+		memset (ufs_inode, 0, sizeof(struct ufs2_inode));
+	UFSD("EXIT\n");
+}
+
+static int ufs_update_inode(struct inode * inode, int do_sync)
+{
+	struct super_block *sb = inode->i_sb;
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+	struct buffer_head * bh;
+
+	UFSD("ENTER, ino %lu\n", inode->i_ino);
+
+	if (inode->i_ino < UFS_ROOTINO ||
+	    inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
+		ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
+		return -1;
+	}
+
+	bh = sb_bread(sb, ufs_inotofsba(inode->i_ino));
+	if (!bh) {
+		ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
+		return -1;
+	}
+	if (uspi->fs_magic == UFS2_MAGIC) {
+		struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;
+
+		ufs2_update_inode(inode,
+				  ufs2_inode + ufs_inotofsbo(inode->i_ino));
+	} else {
+		struct ufs_inode *ufs_inode = (struct ufs_inode *) bh->b_data;
+
+		ufs1_update_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
+	}
 		
 	mark_buffer_dirty(bh);
 	if (do_sync)
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index e84c0ec..a059ccd 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -355,7 +355,7 @@
 	return err;
 }
 
-struct inode_operations ufs_dir_inode_operations = {
+const struct inode_operations ufs_dir_inode_operations = {
 	.create		= ufs_create,
 	.lookup		= ufs_lookup,
 	.link		= ufs_link,
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 209be95..b5a6461 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -61,6 +61,8 @@
  * UFS2 (of FreeBSD 5.x) support added by
  * Niraj Kumar <niraj17@iitbombay.org>, Jan 2004
  *
+ * UFS2 write support added by
+ * Evgeniy Dushistov <dushistov@mail.ru>, 2007
  */
 
 
@@ -93,14 +95,16 @@
 /*
  * Print contents of ufs_super_block, useful for debugging
  */
-static void ufs_print_super_stuff(struct super_block *sb, unsigned flags,
+static void ufs_print_super_stuff(struct super_block *sb,
 				  struct ufs_super_block_first *usb1,
 				  struct ufs_super_block_second *usb2,
 				  struct ufs_super_block_third *usb3)
 {
+	u32 magic = fs32_to_cpu(sb, usb3->fs_magic);
+
 	printk("ufs_print_super_stuff\n");
-	printk("  magic:     0x%x\n", fs32_to_cpu(sb, usb3->fs_magic));
-	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+	printk("  magic:     0x%x\n", magic);
+	if (fs32_to_cpu(sb, usb3->fs_magic) == UFS2_MAGIC) {
 		printk("  fs_size:   %llu\n", (unsigned long long)
 		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size));
 		printk("  fs_dsize:  %llu\n", (unsigned long long)
@@ -117,6 +121,12 @@
 		printk("  cs_nbfree(No of free blocks):  %llu\n",
 		       (unsigned long long)
 		       fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree));
+		printk(KERN_INFO"  cs_nifree(Num of free inodes): %llu\n",
+		       (unsigned long long)
+		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree));
+		printk(KERN_INFO"  cs_nffree(Num of free frags): %llu\n",
+		       (unsigned long long)
+		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree));
 	} else {
 		printk(" sblkno:      %u\n", fs32_to_cpu(sb, usb1->fs_sblkno));
 		printk(" cblkno:      %u\n", fs32_to_cpu(sb, usb1->fs_cblkno));
@@ -199,11 +209,11 @@
 	printk("\n");
 }
 #else
-#  define ufs_print_super_stuff(sb, flags, usb1, usb2, usb3) /**/
+#  define ufs_print_super_stuff(sb, usb1, usb2, usb3) /**/
 #  define ufs_print_cylinder_stuff(sb, cg) /**/
 #endif /* CONFIG_UFS_DEBUG */
 
-static struct super_operations ufs_super_ops;
+static const struct super_operations ufs_super_ops;
 
 static char error_buf[1024];
 
@@ -422,7 +432,6 @@
 {
 	struct ufs_sb_info *sbi = UFS_SB(sb);
 	struct ufs_sb_private_info *uspi = sbi->s_uspi;
-	unsigned flags = sbi->s_flags;
 	struct ufs_buffer_head * ubh;
 	unsigned char * base, * space;
 	unsigned size, blks, i;
@@ -446,11 +455,7 @@
 		if (i + uspi->s_fpb > blks)
 			size = (blks - i) * uspi->s_fsize;
 
-		if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 
-			ubh = ubh_bread(sb,
-				fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr) + i, size);
-		else 
-			ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
+		ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
 		
 		if (!ubh)
 			goto failed;
@@ -545,6 +550,7 @@
 			cpu_to_fs32(sb, uspi->cs_total.cs_nffree);
 	}
 	ubh_mark_buffer_dirty(USPI_UBH(uspi));
+	ufs_print_super_stuff(sb, usb1, usb2, usb3);
 	UFSD("EXIT\n");
 }
 
@@ -572,7 +578,9 @@
 		size = uspi->s_bsize;
 		if (i + uspi->s_fpb > blks)
 			size = (blks - i) * uspi->s_fsize;
+
 		ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
+
 		ubh_memcpyubh (ubh, space, size);
 		space += size;
 		ubh_mark_buffer_uptodate (ubh, 1);
@@ -674,10 +682,6 @@
 		uspi->s_sbsize = super_block_size = 1536;
 		uspi->s_sbbase =  0;
 		flags |= UFS_TYPE_UFS2 | UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
-		if (!(sb->s_flags & MS_RDONLY)) {
-			printk(KERN_INFO "ufstype=ufs2 is supported read-only\n");
-			sb->s_flags |= MS_RDONLY;
- 		}
 		break;
 		
 	case UFS_MOUNT_UFSTYPE_SUN:
@@ -890,7 +894,7 @@
 	}
 
 
-	ufs_print_super_stuff(sb, flags, usb1, usb2, usb3);
+	ufs_print_super_stuff(sb, usb1, usb2, usb3);
 
 	/*
 	 * Check, if file system was correctly unmounted.
@@ -973,7 +977,12 @@
 	uspi->s_npsect = ufs_get_fs_npsect(sb, usb1, usb3);
 	uspi->s_interleave = fs32_to_cpu(sb, usb1->fs_interleave);
 	uspi->s_trackskew = fs32_to_cpu(sb, usb1->fs_trackskew);
-	uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr);
+
+	if (uspi->fs_magic == UFS2_MAGIC)
+		uspi->s_csaddr = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr);
+	else
+		uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr);
+
 	uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize);
 	uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize);
 	uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak);
@@ -1060,7 +1069,6 @@
 	unsigned flags;
 
 	lock_kernel();
-
 	UFSD("ENTER\n");
 	flags = UFS_SB(sb)->s_flags;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -1156,7 +1164,8 @@
 #else
 		if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 
 		    ufstype != UFS_MOUNT_UFSTYPE_44BSD &&
-		    ufstype != UFS_MOUNT_UFSTYPE_SUNx86) {
+		    ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
+		    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
 			printk("this ufstype is read-only supported\n");
 			return -EINVAL;
 		}
@@ -1255,7 +1264,7 @@
 static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t);
 #endif
 
-static struct super_operations ufs_super_ops = {
+static const struct super_operations ufs_super_ops = {
 	.alloc_inode	= ufs_alloc_inode,
 	.destroy_inode	= ufs_destroy_inode,
 	.read_inode	= ufs_read_inode,
diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c
index 337512e..d8549f8 100644
--- a/fs/ufs/symlink.c
+++ b/fs/ufs/symlink.c
@@ -36,7 +36,7 @@
 	return NULL;
 }
 
-struct inode_operations ufs_fast_symlink_inode_operations = {
+const struct inode_operations ufs_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= ufs_follow_link,
 };
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index 0437b0a..749581f 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -30,8 +30,8 @@
  */
 
 /*
- * Modified to avoid infinite loop on 2006 by
- * Evgeniy Dushistov <dushistov@mail.ru>
+ * Adoptation to use page cache and UFS2 write support by
+ * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007
  */
 
 #include <linux/errno.h>
@@ -63,13 +63,13 @@
 #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
 
 
-static int ufs_trunc_direct (struct inode * inode)
+static int ufs_trunc_direct(struct inode *inode)
 {
 	struct ufs_inode_info *ufsi = UFS_I(inode);
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	__fs32 * p;
-	unsigned frag1, frag2, frag3, frag4, block1, block2;
+	void *p;
+	u64 frag1, frag2, frag3, frag4, block1, block2;
 	unsigned frag_to_free, free_count;
 	unsigned i, tmp;
 	int retry;
@@ -91,13 +91,16 @@
 	if (frag2 > frag3) {
 		frag2 = frag4;
 		frag3 = frag4 = 0;
-	}
-	else if (frag2 < frag3) {
+	} else if (frag2 < frag3) {
 		block1 = ufs_fragstoblks (frag2);
 		block2 = ufs_fragstoblks (frag3);
 	}
 
-	UFSD("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4);
+	UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu,"
+	     " frag4 %llu\n",
+	     (unsigned long long)frag1, (unsigned long long)frag2,
+	     (unsigned long long)block1, (unsigned long long)block2,
+	     (unsigned long long)frag3, (unsigned long long)frag4);
 
 	if (frag1 >= frag2)
 		goto next1;		
@@ -105,8 +108,8 @@
 	/*
 	 * Free first free fragments
 	 */
-	p = ufsi->i_u1.i_data + ufs_fragstoblks (frag1);
-	tmp = fs32_to_cpu(sb, *p);
+	p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1));
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (!tmp )
 		ufs_panic (sb, "ufs_trunc_direct", "internal error");
 	frag2 -= frag1;
@@ -121,12 +124,11 @@
 	 * Free whole blocks
 	 */
 	for (i = block1 ; i < block2; i++) {
-		p = ufsi->i_u1.i_data + i;
-		tmp = fs32_to_cpu(sb, *p);
+		p = ufs_get_direct_data_ptr(uspi, ufsi, i);
+		tmp = ufs_data_ptr_to_cpu(sb, p);
 		if (!tmp)
 			continue;
-
-		*p = 0;
+		ufs_data_ptr_clear(uspi, p);
 
 		if (free_count == 0) {
 			frag_to_free = tmp;
@@ -150,13 +152,12 @@
 	/*
 	 * Free last free fragments
 	 */
-	p = ufsi->i_u1.i_data + ufs_fragstoblks (frag3);
-	tmp = fs32_to_cpu(sb, *p);
+	p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3));
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (!tmp )
 		ufs_panic(sb, "ufs_truncate_direct", "internal error");
 	frag4 = ufs_fragnum (frag4);
-
-	*p = 0;
+	ufs_data_ptr_clear(uspi, p);
 
 	ufs_free_fragments (inode, tmp, frag4);
 	mark_inode_dirty(inode);
@@ -167,17 +168,20 @@
 }
 
 
-static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
+static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * ind_ubh;
-	__fs32 * ind;
-	unsigned indirect_block, i, tmp;
-	unsigned frag_to_free, free_count;
+	void *ind;
+	u64 tmp, indirect_block, i, frag_to_free;
+	unsigned free_count;
 	int retry;
 
-	UFSD("ENTER\n");
+	UFSD("ENTER: ino %lu, offset %llu, p: %p\n",
+	     inode->i_ino, (unsigned long long)offset, p);
+
+	BUG_ON(!p);
 		
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -186,27 +190,27 @@
 	free_count = 0;
 	retry = 0;
 	
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (!tmp)
 		return 0;
 	ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize);
-	if (tmp != fs32_to_cpu(sb, *p)) {
+	if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 		ubh_brelse (ind_ubh);
 		return 1;
 	}
 	if (!ind_ubh) {
-		*p = 0;
+		ufs_data_ptr_clear(uspi, p);
 		return 0;
 	}
 
 	indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0;
 	for (i = indirect_block; i < uspi->s_apb; i++) {
-		ind = ubh_get_addr32 (ind_ubh, i);
-		tmp = fs32_to_cpu(sb, *ind);
+		ind = ubh_get_data_ptr(uspi, ind_ubh, i);
+		tmp = ufs_data_ptr_to_cpu(sb, ind);
 		if (!tmp)
 			continue;
 
-		*ind = 0;
+		ufs_data_ptr_clear(uspi, ind);
 		ubh_mark_buffer_dirty(ind_ubh);
 		if (free_count == 0) {
 			frag_to_free = tmp;
@@ -226,11 +230,12 @@
 		ufs_free_blocks (inode, frag_to_free, free_count);
 	}
 	for (i = 0; i < uspi->s_apb; i++)
-		if (*ubh_get_addr32(ind_ubh,i))
+		if (!ufs_is_data_ptr_zero(uspi,
+					  ubh_get_data_ptr(uspi, ind_ubh, i)))
 			break;
 	if (i >= uspi->s_apb) {
-		tmp = fs32_to_cpu(sb, *p);
-		*p = 0;
+		tmp = ufs_data_ptr_to_cpu(sb, p);
+		ufs_data_ptr_clear(uspi, p);
 
 		ufs_free_blocks (inode, tmp, uspi->s_fpb);
 		mark_inode_dirty(inode);
@@ -248,13 +253,13 @@
 	return retry;
 }
 
-static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
+static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
-	struct ufs_buffer_head * dind_bh;
-	unsigned i, tmp, dindirect_block;
-	__fs32 * dind;
+	struct ufs_buffer_head *dind_bh;
+	u64 i, tmp, dindirect_block;
+	void *dind;
 	int retry = 0;
 	
 	UFSD("ENTER\n");
@@ -266,22 +271,22 @@
 		? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0;
 	retry = 0;
 	
-	tmp = fs32_to_cpu(sb, *p);
+	tmp = ufs_data_ptr_to_cpu(sb, p);
 	if (!tmp)
 		return 0;
 	dind_bh = ubh_bread(sb, tmp, uspi->s_bsize);
-	if (tmp != fs32_to_cpu(sb, *p)) {
+	if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 		ubh_brelse (dind_bh);
 		return 1;
 	}
 	if (!dind_bh) {
-		*p = 0;
+		ufs_data_ptr_clear(uspi, p);
 		return 0;
 	}
 
 	for (i = dindirect_block ; i < uspi->s_apb ; i++) {
-		dind = ubh_get_addr32 (dind_bh, i);
-		tmp = fs32_to_cpu(sb, *dind);
+		dind = ubh_get_data_ptr(uspi, dind_bh, i);
+		tmp = ufs_data_ptr_to_cpu(sb, dind);
 		if (!tmp)
 			continue;
 		retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind);
@@ -289,11 +294,12 @@
 	}
 
 	for (i = 0; i < uspi->s_apb; i++)
-		if (*ubh_get_addr32 (dind_bh, i))
+		if (!ufs_is_data_ptr_zero(uspi,
+					  ubh_get_data_ptr(uspi, dind_bh, i)))
 			break;
 	if (i >= uspi->s_apb) {
-		tmp = fs32_to_cpu(sb, *p);
-		*p = 0;
+		tmp = ufs_data_ptr_to_cpu(sb, p);
+		ufs_data_ptr_clear(uspi, p);
 
 		ufs_free_blocks(inode, tmp, uspi->s_fpb);
 		mark_inode_dirty(inode);
@@ -311,34 +317,33 @@
 	return retry;
 }
 
-static int ufs_trunc_tindirect (struct inode * inode)
+static int ufs_trunc_tindirect(struct inode *inode)
 {
+	struct super_block *sb = inode->i_sb;
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct ufs_inode_info *ufsi = UFS_I(inode);
-	struct super_block * sb;
-	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * tind_bh;
-	unsigned tindirect_block, tmp, i;
-	__fs32 * tind, * p;
+	u64 tindirect_block, tmp, i;
+	void *tind, *p;
 	int retry;
 	
 	UFSD("ENTER\n");
 
-	sb = inode->i_sb;
-	uspi = UFS_SB(sb)->s_uspi;
 	retry = 0;
 	
 	tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb))
 		? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0;
-	p = ufsi->i_u1.i_data + UFS_TIND_BLOCK;
-	if (!(tmp = fs32_to_cpu(sb, *p)))
+
+	p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK);
+	if (!(tmp = ufs_data_ptr_to_cpu(sb, p)))
 		return 0;
 	tind_bh = ubh_bread (sb, tmp, uspi->s_bsize);
-	if (tmp != fs32_to_cpu(sb, *p)) {
+	if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 		ubh_brelse (tind_bh);
 		return 1;
 	}
 	if (!tind_bh) {
-		*p = 0;
+		ufs_data_ptr_clear(uspi, p);
 		return 0;
 	}
 
@@ -349,11 +354,12 @@
 		ubh_mark_buffer_dirty(tind_bh);
 	}
 	for (i = 0; i < uspi->s_apb; i++)
-		if (*ubh_get_addr32 (tind_bh, i))
+		if (!ufs_is_data_ptr_zero(uspi,
+					  ubh_get_data_ptr(uspi, tind_bh, i)))
 			break;
 	if (i >= uspi->s_apb) {
-		tmp = fs32_to_cpu(sb, *p);
-		*p = 0;
+		tmp = ufs_data_ptr_to_cpu(sb, p);
+		ufs_data_ptr_clear(uspi, p);
 
 		ufs_free_blocks(inode, tmp, uspi->s_fpb);
 		mark_inode_dirty(inode);
@@ -375,7 +381,8 @@
 	int err = 0;
 	struct address_space *mapping = inode->i_mapping;
 	struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi;
-	unsigned lastfrag, i, end;
+	unsigned i, end;
+	sector_t lastfrag;
 	struct page *lastpage;
 	struct buffer_head *bh;
 
@@ -430,7 +437,9 @@
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	int retry, err = 0;
 	
-	UFSD("ENTER\n");
+	UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n",
+	     inode->i_ino, (unsigned long long)i_size_read(inode),
+	     (unsigned long long)old_i_size);
 
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 	      S_ISLNK(inode->i_mode)))
@@ -450,10 +459,12 @@
 	lock_kernel();
 	while (1) {
 		retry = ufs_trunc_direct(inode);
-		retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK,
-			(__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]);
-		retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb,
-			(__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]);
+		retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK,
+					    ufs_get_direct_data_ptr(uspi, ufsi,
+								    UFS_IND_BLOCK));
+		retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb,
+					     ufs_get_direct_data_ptr(uspi, ufsi,
+								     UFS_DIND_BLOCK));
 		retry |= ufs_trunc_tindirect (inode);
 		if (!retry)
 			break;
@@ -502,6 +513,6 @@
 	return inode_setattr(inode, attr);
 }
 
-struct inode_operations ufs_file_inode_operations = {
+const struct inode_operations ufs_file_inode_operations = {
 	.setattr = ufs_setattr,
 };
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index 7dd12bb..06d3448 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -305,8 +305,22 @@
 	(((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
 	((begin) & ((uspi->s_fsize>>2) - 1)))
 
+#define ubh_get_addr64(ubh,begin) \
+	(((__fs64*)((ubh)->bh[(begin) >> (uspi->s_fshift-3)]->b_data)) + \
+	((begin) & ((uspi->s_fsize>>3) - 1)))
+
 #define ubh_get_addr ubh_get_addr8
 
+static inline void *ubh_get_data_ptr(struct ufs_sb_private_info *uspi,
+				     struct ufs_buffer_head *ubh,
+				     u64 blk)
+{
+	if (uspi->fs_magic == UFS2_MAGIC)
+		return ubh_get_addr64(ubh, blk);
+	else
+		return ubh_get_addr32(ubh, blk);
+}
+
 #define ubh_blkmap(ubh,begin,bit) \
 	((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb)))
 
@@ -507,3 +521,46 @@
 	if (fragsize > 0 && fragsize < uspi->s_fpb)
 		fs32_add(sb, &fraglist[fragsize], cnt);
 }
+
+static inline void *ufs_get_direct_data_ptr(struct ufs_sb_private_info *uspi,
+					    struct ufs_inode_info *ufsi,
+					    unsigned blk)
+{
+	BUG_ON(blk > UFS_TIND_BLOCK);
+	return uspi->fs_magic == UFS2_MAGIC ?
+		(void *)&ufsi->i_u1.u2_i_data[blk] :
+		(void *)&ufsi->i_u1.i_data[blk];
+}
+
+static inline u64 ufs_data_ptr_to_cpu(struct super_block *sb, void *p)
+{
+	return UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC ?
+		fs64_to_cpu(sb, *(__fs64 *)p) :
+		fs32_to_cpu(sb, *(__fs32 *)p);
+}
+
+static inline void ufs_cpu_to_data_ptr(struct super_block *sb, void *p, u64 val)
+{
+	if (UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC)
+		*(__fs64 *)p = cpu_to_fs64(sb, val);
+	else
+		*(__fs32 *)p = cpu_to_fs32(sb, val);
+}
+
+static inline void ufs_data_ptr_clear(struct ufs_sb_private_info *uspi,
+				      void *p)
+{
+	if (uspi->fs_magic == UFS2_MAGIC)
+		*(__fs64 *)p = 0;
+	else
+		*(__fs32 *)p = 0;
+}
+
+static inline int ufs_is_data_ptr_zero(struct ufs_sb_private_info *uspi,
+				       void *p)
+{
+	if (uspi->fs_magic == UFS2_MAGIC)
+		return *(__fs64 *)p == 0;
+	else
+		return *(__fs32 *)p == 0;
+}
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 0afd745..c28add2 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -996,7 +996,7 @@
 	goto out;
 }
 
-static struct inode_operations vfat_dir_inode_operations = {
+static const struct inode_operations vfat_dir_inode_operations = {
 	.create		= vfat_create,
 	.lookup		= vfat_lookup,
 	.unlink		= vfat_unlink,
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index f3cc4ab..143ffc8 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -56,8 +56,6 @@
 	do {
 		if (buffer_uptodate(bh) && !buffer_mapped(bh))
 			(*unmapped) = 1;
-		else if (buffer_unwritten(bh) && !buffer_delay(bh))
-			clear_buffer_unwritten(bh);
 		else if (buffer_unwritten(bh))
 			(*unwritten) = 1;
 		else if (buffer_delay(bh))
@@ -1272,7 +1270,6 @@
 			if (direct)
 				bh_result->b_private = inode;
 			set_buffer_unwritten(bh_result);
-			set_buffer_delay(bh_result);
 		}
 	}
 
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index aa4c3b8..0b5fa12 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -813,7 +813,7 @@
 }
 
 
-struct inode_operations xfs_inode_operations = {
+const struct inode_operations xfs_inode_operations = {
 	.permission		= xfs_vn_permission,
 	.truncate		= xfs_vn_truncate,
 	.getattr		= xfs_vn_getattr,
@@ -824,7 +824,7 @@
 	.removexattr		= xfs_vn_removexattr,
 };
 
-struct inode_operations xfs_dir_inode_operations = {
+const struct inode_operations xfs_dir_inode_operations = {
 	.create			= xfs_vn_create,
 	.lookup			= xfs_vn_lookup,
 	.link			= xfs_vn_link,
@@ -843,7 +843,7 @@
 	.removexattr		= xfs_vn_removexattr,
 };
 
-struct inode_operations xfs_symlink_inode_operations = {
+const struct inode_operations xfs_symlink_inode_operations = {
 	.readlink		= generic_readlink,
 	.follow_link		= xfs_vn_follow_link,
 	.put_link		= xfs_vn_put_link,
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index ad6173d..95a6939 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -18,9 +18,9 @@
 #ifndef __XFS_IOPS_H__
 #define __XFS_IOPS_H__
 
-extern struct inode_operations xfs_inode_operations;
-extern struct inode_operations xfs_dir_inode_operations;
-extern struct inode_operations xfs_symlink_inode_operations;
+extern const struct inode_operations xfs_inode_operations;
+extern const struct inode_operations xfs_dir_inode_operations;
+extern const struct inode_operations xfs_symlink_inode_operations;
 
 extern const struct file_operations xfs_file_operations;
 extern const struct file_operations xfs_dir_file_operations;
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 2b0e001..715adad 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -109,16 +109,6 @@
 #undef  HAVE_PERCPU_SB	/* per cpu superblock counters are a 2.6 feature */
 #endif
 
-/*
- * State flag for unwritten extent buffers.
- *
- * We need to be able to distinguish between these and delayed
- * allocate buffers within XFS.  The generic IO path code does
- * not need to distinguish - we use the BH_Delay flag for both
- * delalloc and these ondisk-uninitialised buffers.
- */
-BUFFER_FNS(PrivateStart, unwritten);
-
 #define restricted_chown	xfs_params.restrict_chown.val
 #define irix_sgid_inherit	xfs_params.sgid_inherit.val
 #define irix_symlink_mode	xfs_params.symlink_mode.val
diff --git a/include/asm-arm/arch-at91rm9200/gpio.h b/include/asm-arm/arch-at91rm9200/gpio.h
index a011d27..e09d652 100644
--- a/include/asm-arm/arch-at91rm9200/gpio.h
+++ b/include/asm-arm/arch-at91rm9200/gpio.h
@@ -179,6 +179,7 @@
 
 #ifndef __ASSEMBLY__
 /* setup setup routines, called from board init or driver probe() */
+extern int __init_or_module at91_set_GPIO_periph(unsigned pin, int use_pullup);
 extern int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup);
 extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup);
 extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup);
@@ -193,7 +194,50 @@
 /* callable only from core power-management code */
 extern void at91_gpio_suspend(void);
 extern void at91_gpio_resume(void);
-#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* wrappers for "new style" GPIO calls. the old AT91-specfic ones should
+ * eventually be removed (along with this errno.h inclusion), and the
+ * gpio request/free calls should probably be implemented.
+ */
+
+#include <asm/errno.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+}
+
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio);
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return at91_get_gpio_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	at91_set_gpio_value(gpio, value);
+}
+
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return irq;
+}
+
+#endif	/* __ASSEMBLY__ */
 
 #endif
-
diff --git a/include/asm-arm/arch-imx/spi_imx.h b/include/asm-arm/arch-imx/spi_imx.h
new file mode 100644
index 0000000..2165449
--- /dev/null
+++ b/include/asm-arm/arch-imx/spi_imx.h
@@ -0,0 +1,72 @@
+/*
+ * include/asm-arm/arch-imx/spi_imx.h
+ *
+ * Copyright (C) 2006 SWAPP
+ *	Andrea Paterniani <a.paterniani@swapp-eng.it>
+ *
+ * Initial version inspired by:
+ *	linux-2.6.17-rc3-mm1/include/asm-arm/arch-pxa/pxa2xx_spi.h
+ *
+ * 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.
+ */
+
+#ifndef SPI_IMX_H_
+#define SPI_IMX_H_
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ * struct spi_imx_master - device.platform_data for SPI controller devices.
+ * @num_chipselect: chipselects are used to distinguish individual
+ *	SPI slaves, and are numbered from zero to num_chipselects - 1.
+ *	each slave has a chipselect signal, but it's common that not
+ *	every chipselect is connected to a slave.
+ * @enable_dma: if true enables DMA driven transfers.
+*/
+struct spi_imx_master {
+	u8 num_chipselect;
+	u8 enable_dma:1;
+};
+/*-------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ * struct spi_imx_chip - spi_board_info.controller_data for SPI
+ * slave devices, copied to spi_device.controller_data.
+ * @enable_loopback : used for test purpouse to internally connect RX and TX
+ *	sections.
+ * @enable_dma : enables dma transfer (provided that controller driver has
+ *	dma enabled too).
+ * @ins_ss_pulse : enable /SS pulse insertion between SPI burst.
+ * @bclk_wait : number of bclk waits between each bits_per_word SPI burst.
+ * @cs_control : function pointer to board-specific function to assert/deassert
+ *	I/O port to control HW generation of devices chip-select.
+*/
+struct spi_imx_chip {
+	u8	enable_loopback:1;
+	u8	enable_dma:1;
+	u8	ins_ss_pulse:1;
+	u16	bclk_wait:15;
+	void (*cs_control)(u32 control);
+};
+
+/* Chip-select state */
+#define SPI_CS_ASSERT			(1 << 0)
+#define SPI_CS_DEASSERT			(1 << 1)
+/*-------------------------------------------------------------------------*/
+
+
+#endif /* SPI_IMX_H_*/
diff --git a/include/asm-arm/arch-omap/gpio.h b/include/asm-arm/arch-omap/gpio.h
index f486b72..3762a6a 100644
--- a/include/asm-arm/arch-omap/gpio.h
+++ b/include/asm-arm/arch-omap/gpio.h
@@ -76,4 +76,70 @@
 extern void omap_set_gpio_dataout(int gpio, int enable);
 extern int omap_get_gpio_datain(int gpio);
 
+/*-------------------------------------------------------------------------*/
+
+/* wrappers for "new style" GPIO calls. the old OMAP-specfic ones should
+ * eventually be removed (along with this errno.h inclusion), and maybe
+ * gpios should put MPUIOs last too.
+ */
+
+#include <asm/errno.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return omap_request_gpio(gpio);
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	omap_free_gpio(gpio);
+}
+
+static inline int __gpio_set_direction(unsigned gpio, int is_input)
+{
+	if (cpu_class_is_omap2()) {
+		if (gpio > OMAP_MAX_GPIO_LINES)
+			return -EINVAL;
+	} else {
+		if (gpio > (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */))
+			return -EINVAL;
+	}
+	omap_set_gpio_direction(gpio, is_input);
+	return 0;
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	return __gpio_set_direction(gpio, 1);
+}
+
+static inline int gpio_direction_output(unsigned gpio)
+{
+	return __gpio_set_direction(gpio, 0);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return omap_get_gpio_datain(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	omap_set_gpio_dataout(gpio, value);
+}
+
+#include <asm-generic/gpio.h>		/* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return OMAP_GPIO_IRQ(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	if (cpu_class_is_omap1() && (irq < (IH_MPUIO_BASE + 16)))
+		return (irq - IH_MPUIO_BASE) + OMAP_MAX_GPIO_LINES;
+	return irq - IH_GPIO_BASE;
+}
+
 #endif
diff --git a/include/asm-arm/arch-pxa/gpio.h b/include/asm-arm/arch-pxa/gpio.h
new file mode 100644
index 0000000..e67c238
--- /dev/null
+++ b/include/asm-arm/arch-pxa/gpio.h
@@ -0,0 +1,72 @@
+/*
+ * linux/include/asm-arm/arch-pxa/gpio.h
+ *
+ * PXA GPIO wrappers for arch-neutral GPIO calls
+ *
+ * Written by Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __ASM_ARCH_PXA_GPIO_H
+#define __ASM_ARCH_PXA_GPIO_H
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+
+#include <asm/errno.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	return;
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	if (gpio > PXA_LAST_GPIO)
+		return -EINVAL;
+	pxa_gpio_mode(gpio | GPIO_IN);
+}
+
+static inline int gpio_direction_output(unsigned gpio)
+{
+	if (gpio > PXA_LAST_GPIO)
+		return -EINVAL;
+	pxa_gpio_mode(gpio | GPIO_OUT);
+}
+
+/* REVISIT these macros are correct, but suffer code explosion
+ * for non-constant parameters.  Provide out-line versions too.
+ */
+#define gpio_get_value(gpio) \
+	(GPLR(gpio) & GPIO_bit(gpio))
+
+#define gpio_set_value(gpio,value) \
+	((value) ? (GPSR(gpio) = GPIO_bit(gpio)):(GPCR(gpio) = GPIO_bit(gpio)))
+
+#include <asm-generic/gpio.h>			/* cansleep wrappers */
+
+#define gpio_to_irq(gpio)	IRQ_GPIO(gpio)
+#define irq_to_gpio(irq)	IRQ_TO_GPIO(irq)
+
+
+#endif
diff --git a/include/asm-arm/arch-s3c2410/gpio.h b/include/asm-arm/arch-s3c2410/gpio.h
new file mode 100644
index 0000000..67b8b9a
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/gpio.h
@@ -0,0 +1,65 @@
+/*
+ * linux/include/asm-arm/arch-pxa/gpio.h
+ *
+ * S3C2400 GPIO wrappers for arch-neutral GPIO calls
+ *
+ * Written by Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __ASM_ARCH_PXA_GPIO_H
+#define __ASM_ARCH_PXA_GPIO_H
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+
+#include <asm/errno.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	return;
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	s3c2410_gpio_cfgpin(gpio, S3C2410_GPIO_INPUT);
+	return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio)
+{
+	s3c2410_gpio_cfgpin(gpio, S3C2410_GPIO_OUTPUT);
+	return 0;
+}
+
+#define gpio_get_value(gpio)		s3c2410_gpio_getpin(gpio)
+#define gpio_set_value(gpio,value)	s3c2410_gpio_setpin(gpio, value)
+
+#include <asm-generic/gpio.h>			/* cansleep wrappers */
+
+/* FIXME or maybe s3c2400_gpio_getirq() ... */
+#define gpio_to_irq(gpio)		s3c2410_gpio_getirq(gpio)
+
+/* FIXME implement irq_to_gpio() */
+
+#endif
diff --git a/include/asm-arm/arch-sa1100/gpio.h b/include/asm-arm/arch-sa1100/gpio.h
new file mode 100644
index 0000000..a331fe3
--- /dev/null
+++ b/include/asm-arm/arch-sa1100/gpio.h
@@ -0,0 +1,81 @@
+/*
+ * linux/include/asm-arm/arch-pxa/gpio.h
+ *
+ * SA1100 GPIO wrappers for arch-neutral GPIO calls
+ *
+ * Written by Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __ASM_ARCH_SA1100_GPIO_H
+#define __ASM_ARCH_SA1100_GPIO_H
+
+#include <asm/arch/SA-1100.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+
+#include <asm/errno.h>
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+	return;
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+	if (gpio > GPIO_MAX)
+		return -EINVAL;
+	GPDR = (GPDR_In << gpio) 0
+}
+
+static inline int gpio_direction_output(unsigned gpio)
+{
+	if (gpio > GPIO_MAX)
+		return -EINVAL;
+	GPDR = (GPDR_Out << gpio) 0
+}
+
+#define gpio_get_value(gpio) \
+	(GPLR & GPIO_GPIO(gpio))
+
+#define gpio_set_value(gpio,value) \
+	((value) ? (GPSR = GPIO_GPIO(gpio)) : (GPCR(gpio) = GPIO_GPIO(gpio)))
+
+#include <asm-generic/gpio.h>			/* cansleep wrappers */
+
+static inline unsigned gpio_to_irq(unsigned gpio)
+{
+	if (gpio < 11)
+		return IRQ_GPIO0 + gpio;
+	else
+		return IRQ_GPIO11 - 11 + gpio;
+}
+
+static inline unsigned irq_to_gpio(unsigned irq)
+{
+	if (irq < IRQ_GPIO11_27)
+		return irq - IRQ_GPIO0;
+	else
+		return irq - IRQ_GPIO11 + 11;
+}
+
+#endif
diff --git a/include/asm-arm/gpio.h b/include/asm-arm/gpio.h
new file mode 100644
index 0000000..fff4f80
--- /dev/null
+++ b/include/asm-arm/gpio.h
@@ -0,0 +1,7 @@
+#ifndef _ARCH_ARM_GPIO_H
+#define _ARCH_ARM_GPIO_H
+
+/* not all ARM platforms necessarily support this API ... */
+#include <asm/arch/gpio.h>
+
+#endif /* _ARCH_ARM_GPIO_H */
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
new file mode 100644
index 0000000..2d0aab1
--- /dev/null
+++ b/include/asm-generic/gpio.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_GPIO_H
+#define _ASM_GENERIC_GPIO_H
+
+/* platforms that don't directly support access to GPIOs through I2C, SPI,
+ * or other blocking infrastructure can use these wrappers.
+ */
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+	return 0;
+}
+
+static inline int gpio_get_value_cansleep(unsigned gpio)
+{
+	might_sleep();
+	return gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value_cansleep(unsigned gpio, int value)
+{
+	might_sleep();
+	gpio_set_value(gpio, value);
+}
+
+#endif /* _ASM_GENERIC_GPIO_H */
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index 67659db..7631627 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -6,7 +6,7 @@
 #ifndef _i386_SETUP_H
 #define _i386_SETUP_H
 
-#define COMMAND_LINE_SIZE 256
+#define COMMAND_LINE_SIZE 2048
 
 #ifdef __KERNEL__
 #include <linux/pfn.h>
diff --git a/include/asm-ia64/setup.h b/include/asm-ia64/setup.h
index ea29b57..4399a44 100644
--- a/include/asm-ia64/setup.h
+++ b/include/asm-ia64/setup.h
@@ -1,6 +1,6 @@
 #ifndef __IA64_SETUP_H
 #define __IA64_SETUP_H
 
-#define COMMAND_LINE_SIZE	512
+#define COMMAND_LINE_SIZE	2048
 
 #endif
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
index 703970f..4869513 100644
--- a/include/asm-powerpc/Kbuild
+++ b/include/asm-powerpc/Kbuild
@@ -23,6 +23,7 @@
 header-y += resource.h
 header-y += sigcontext.h
 header-y += statfs.h
+header-y += ps3fb.h
 
 unifdef-y += a.out.h
 unifdef-y += asm-compat.h
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 4f5a1e0..e5982ad 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -388,4 +388,13 @@
 
 int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev);
 
+struct ps3_prealloc {
+    const char *name;
+    void *address;
+    unsigned long size;
+    unsigned long align;
+};
+
+extern struct ps3_prealloc ps3fb_videomemory;
+
 #endif
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h
new file mode 100644
index 0000000..43e90ea
--- /dev/null
+++ b/include/asm-powerpc/ps3av.h
@@ -0,0 +1,738 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * 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 of the License.
+ *
+ * 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.
+ */
+#ifndef _ASM_POWERPC_PS3AV_H_
+#define _ASM_POWERPC_PS3AV_H_
+
+#include <linux/mutex.h>
+
+/** command for ioctl() **/
+#define PS3AV_VERSION 0x205	/* version of ps3av command */
+
+#define PS3AV_CID_AV_INIT              0x00000001
+#define PS3AV_CID_AV_FIN               0x00000002
+#define PS3AV_CID_AV_GET_HW_CONF       0x00000003
+#define PS3AV_CID_AV_GET_MONITOR_INFO  0x00000004
+#define PS3AV_CID_AV_ENABLE_EVENT      0x00000006
+#define PS3AV_CID_AV_DISABLE_EVENT     0x00000007
+#define PS3AV_CID_AV_TV_MUTE           0x0000000a
+
+#define PS3AV_CID_AV_VIDEO_CS          0x00010001
+#define PS3AV_CID_AV_VIDEO_MUTE        0x00010002
+#define PS3AV_CID_AV_VIDEO_DISABLE_SIG 0x00010003
+#define PS3AV_CID_AV_AUDIO_PARAM       0x00020001
+#define PS3AV_CID_AV_AUDIO_MUTE        0x00020002
+#define PS3AV_CID_AV_HDMI_MODE         0x00040001
+
+#define PS3AV_CID_VIDEO_INIT           0x01000001
+#define PS3AV_CID_VIDEO_MODE           0x01000002
+#define PS3AV_CID_VIDEO_FORMAT         0x01000004
+#define PS3AV_CID_VIDEO_PITCH          0x01000005
+
+#define PS3AV_CID_AUDIO_INIT           0x02000001
+#define PS3AV_CID_AUDIO_MODE           0x02000002
+#define PS3AV_CID_AUDIO_MUTE           0x02000003
+#define PS3AV_CID_AUDIO_ACTIVE         0x02000004
+#define PS3AV_CID_AUDIO_INACTIVE       0x02000005
+#define PS3AV_CID_AUDIO_SPDIF_BIT      0x02000006
+#define PS3AV_CID_AUDIO_CTRL           0x02000007
+
+#define PS3AV_CID_EVENT_UNPLUGGED      0x10000001
+#define PS3AV_CID_EVENT_PLUGGED        0x10000002
+#define PS3AV_CID_EVENT_HDCP_DONE      0x10000003
+#define PS3AV_CID_EVENT_HDCP_FAIL      0x10000004
+#define PS3AV_CID_EVENT_HDCP_AUTH      0x10000005
+#define PS3AV_CID_EVENT_HDCP_ERROR     0x10000006
+
+#define PS3AV_CID_AVB_PARAM            0x04000001
+
+/* max backend ports */
+#define PS3AV_HDMI_MAX                 2	/* HDMI_0 HDMI_1 */
+#define PS3AV_AVMULTI_MAX              1	/* AVMULTI_0 */
+#define PS3AV_AV_PORT_MAX              (PS3AV_HDMI_MAX + PS3AV_AVMULTI_MAX)
+#define PS3AV_OPT_PORT_MAX             1	/* SPDIF0 */
+#define PS3AV_HEAD_MAX                 2	/* HEAD_A HEAD_B */
+
+/* num of pkt for PS3AV_CID_AVB_PARAM */
+#define PS3AV_AVB_NUM_VIDEO            PS3AV_HEAD_MAX
+#define PS3AV_AVB_NUM_AUDIO            0	/* not supported */
+#define PS3AV_AVB_NUM_AV_VIDEO         PS3AV_AV_PORT_MAX
+#define PS3AV_AVB_NUM_AV_AUDIO         PS3AV_HDMI_MAX
+
+#define PS3AV_MUTE_PORT_MAX            1	/* num of ports in mute pkt */
+
+/* event_bit */
+#define PS3AV_CMD_EVENT_BIT_UNPLUGGED			(1 << 0)
+#define PS3AV_CMD_EVENT_BIT_PLUGGED			(1 << 1)
+#define PS3AV_CMD_EVENT_BIT_HDCP_DONE			(1 << 2)
+#define PS3AV_CMD_EVENT_BIT_HDCP_FAIL			(1 << 3)
+#define PS3AV_CMD_EVENT_BIT_HDCP_REAUTH			(1 << 4)
+#define PS3AV_CMD_EVENT_BIT_HDCP_TOPOLOGY		(1 << 5)
+
+/* common params */
+/* mute */
+#define PS3AV_CMD_MUTE_OFF				0x0000
+#define PS3AV_CMD_MUTE_ON				0x0001
+/* avport */
+#define PS3AV_CMD_AVPORT_HDMI_0				0x0000
+#define PS3AV_CMD_AVPORT_HDMI_1				0x0001
+#define PS3AV_CMD_AVPORT_AVMULTI_0			0x0010
+#define PS3AV_CMD_AVPORT_SPDIF_0			0x0020
+#define PS3AV_CMD_AVPORT_SPDIF_1			0x0021
+
+/* for av backend */
+/* av_mclk */
+#define PS3AV_CMD_AV_MCLK_128				0x0000
+#define PS3AV_CMD_AV_MCLK_256				0x0001
+#define PS3AV_CMD_AV_MCLK_512				0x0003
+/* av_inputlen */
+#define PS3AV_CMD_AV_INPUTLEN_16			0x02
+#define PS3AV_CMD_AV_INPUTLEN_20			0x0a
+#define PS3AV_CMD_AV_INPUTLEN_24			0x0b
+/* alayout */
+#define PS3AV_CMD_AV_LAYOUT_32				(1 << 0)
+#define PS3AV_CMD_AV_LAYOUT_44				(1 << 1)
+#define PS3AV_CMD_AV_LAYOUT_48				(1 << 2)
+#define PS3AV_CMD_AV_LAYOUT_88				(1 << 3)
+#define PS3AV_CMD_AV_LAYOUT_96				(1 << 4)
+#define PS3AV_CMD_AV_LAYOUT_176				(1 << 5)
+#define PS3AV_CMD_AV_LAYOUT_192				(1 << 6)
+/* hdmi_mode */
+#define PS3AV_CMD_AV_HDMI_MODE_NORMAL			0xff
+#define PS3AV_CMD_AV_HDMI_HDCP_OFF			0x01
+#define PS3AV_CMD_AV_HDMI_EDID_PASS			0x80
+#define PS3AV_CMD_AV_HDMI_DVI				0x40
+
+/* for video module */
+/* video_head */
+#define PS3AV_CMD_VIDEO_HEAD_A				0x0000
+#define PS3AV_CMD_VIDEO_HEAD_B				0x0001
+/* video_cs_out video_cs_in */
+#define PS3AV_CMD_VIDEO_CS_NONE				0x0000
+#define PS3AV_CMD_VIDEO_CS_RGB_8			0x0001
+#define PS3AV_CMD_VIDEO_CS_YUV444_8			0x0002
+#define PS3AV_CMD_VIDEO_CS_YUV422_8			0x0003
+#define PS3AV_CMD_VIDEO_CS_XVYCC_8			0x0004
+#define PS3AV_CMD_VIDEO_CS_RGB_10			0x0005
+#define PS3AV_CMD_VIDEO_CS_YUV444_10			0x0006
+#define PS3AV_CMD_VIDEO_CS_YUV422_10			0x0007
+#define PS3AV_CMD_VIDEO_CS_XVYCC_10			0x0008
+#define PS3AV_CMD_VIDEO_CS_RGB_12			0x0009
+#define PS3AV_CMD_VIDEO_CS_YUV444_12			0x000a
+#define PS3AV_CMD_VIDEO_CS_YUV422_12			0x000b
+#define PS3AV_CMD_VIDEO_CS_XVYCC_12			0x000c
+/* video_vid */
+#define PS3AV_CMD_VIDEO_VID_NONE			0x0000
+#define PS3AV_CMD_VIDEO_VID_480I			0x0001
+#define PS3AV_CMD_VIDEO_VID_576I			0x0003
+#define PS3AV_CMD_VIDEO_VID_480P			0x0005
+#define PS3AV_CMD_VIDEO_VID_576P			0x0006
+#define PS3AV_CMD_VIDEO_VID_1080I_60HZ			0x0007
+#define PS3AV_CMD_VIDEO_VID_1080I_50HZ			0x0008
+#define PS3AV_CMD_VIDEO_VID_720P_60HZ			0x0009
+#define PS3AV_CMD_VIDEO_VID_720P_50HZ			0x000a
+#define PS3AV_CMD_VIDEO_VID_1080P_60HZ			0x000b
+#define PS3AV_CMD_VIDEO_VID_1080P_50HZ			0x000c
+#define PS3AV_CMD_VIDEO_VID_WXGA			0x000d
+#define PS3AV_CMD_VIDEO_VID_SXGA			0x000e
+#define PS3AV_CMD_VIDEO_VID_WUXGA			0x000f
+#define PS3AV_CMD_VIDEO_VID_480I_A			0x0010
+/* video_format */
+#define PS3AV_CMD_VIDEO_FORMAT_BLACK			0x0000
+#define PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT		0x0007
+/* video_order */
+#define PS3AV_CMD_VIDEO_ORDER_RGB			0x0000
+#define PS3AV_CMD_VIDEO_ORDER_BGR			0x0001
+/* video_fmt */
+#define PS3AV_CMD_VIDEO_FMT_X8R8G8B8			0x0000
+/* video_out_format */
+#define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT		0x0000
+/* video_sync */
+#define PS3AV_CMD_VIDEO_SYNC_VSYNC			0x0001
+#define PS3AV_CMD_VIDEO_SYNC_CSYNC			0x0004
+#define PS3AV_CMD_VIDEO_SYNC_HSYNC			0x0010
+
+/* for audio module */
+/* num_of_ch */
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_2			0x0000
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_3			0x0001
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_4			0x0002
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_5			0x0003
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_6			0x0004
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_7			0x0005
+#define PS3AV_CMD_AUDIO_NUM_OF_CH_8			0x0006
+/* audio_fs */
+#define PS3AV_CMD_AUDIO_FS_32K				0x0001
+#define PS3AV_CMD_AUDIO_FS_44K				0x0002
+#define PS3AV_CMD_AUDIO_FS_48K				0x0003
+#define PS3AV_CMD_AUDIO_FS_88K				0x0004
+#define PS3AV_CMD_AUDIO_FS_96K				0x0005
+#define PS3AV_CMD_AUDIO_FS_176K				0x0006
+#define PS3AV_CMD_AUDIO_FS_192K				0x0007
+/* audio_word_bits */
+#define PS3AV_CMD_AUDIO_WORD_BITS_16			0x0001
+#define PS3AV_CMD_AUDIO_WORD_BITS_20			0x0002
+#define PS3AV_CMD_AUDIO_WORD_BITS_24			0x0003
+/* audio_format */
+#define PS3AV_CMD_AUDIO_FORMAT_PCM			0x0001
+#define PS3AV_CMD_AUDIO_FORMAT_BITSTREAM		0x00ff
+/* audio_source */
+#define PS3AV_CMD_AUDIO_SOURCE_SERIAL			0x0000
+#define PS3AV_CMD_AUDIO_SOURCE_SPDIF			0x0001
+/* audio_swap */
+#define PS3AV_CMD_AUDIO_SWAP_0				0x0000
+#define PS3AV_CMD_AUDIO_SWAP_1				0x0000
+/* audio_map */
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_0			0x0000
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_1			0x0001
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_2			0x0002
+#define PS3AV_CMD_AUDIO_MAP_OUTPUT_3			0x0003
+/* audio_layout */
+#define PS3AV_CMD_AUDIO_LAYOUT_2CH			0x0000
+#define PS3AV_CMD_AUDIO_LAYOUT_6CH			0x000b	/* LREClr */
+#define PS3AV_CMD_AUDIO_LAYOUT_8CH			0x001f	/* LREClrXY */
+/* audio_downmix */
+#define PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED		0x0000
+#define PS3AV_CMD_AUDIO_DOWNMIX_PROHIBITED		0x0001
+
+/* audio_port */
+#define PS3AV_CMD_AUDIO_PORT_HDMI_0			( 1 << 0 )
+#define PS3AV_CMD_AUDIO_PORT_HDMI_1			( 1 << 1 )
+#define PS3AV_CMD_AUDIO_PORT_AVMULTI_0			( 1 << 10 )
+#define PS3AV_CMD_AUDIO_PORT_SPDIF_0			( 1 << 20 )
+#define PS3AV_CMD_AUDIO_PORT_SPDIF_1			( 1 << 21 )
+
+/* audio_ctrl_id */
+#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_RESET		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_ID_DAC_DE_EMPHASIS		0x0001
+#define PS3AV_CMD_AUDIO_CTRL_ID_AVCLK			0x0002
+/* audio_ctrl_data[0] reset */
+#define PS3AV_CMD_AUDIO_CTRL_RESET_NEGATE		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_RESET_ASSERT		0x0001
+/* audio_ctrl_data[0] de-emphasis */
+#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_OFF		0x0000
+#define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_ON		0x0001
+/* audio_ctrl_data[0] avclk */
+#define PS3AV_CMD_AUDIO_CTRL_AVCLK_22			0x0000
+#define PS3AV_CMD_AUDIO_CTRL_AVCLK_18			0x0001
+
+/* av_vid */
+/* do not use these params directly, use vid_video2av */
+#define PS3AV_CMD_AV_VID_480I				0x0000
+#define PS3AV_CMD_AV_VID_480P				0x0001
+#define PS3AV_CMD_AV_VID_720P_60HZ			0x0002
+#define PS3AV_CMD_AV_VID_1080I_60HZ			0x0003
+#define PS3AV_CMD_AV_VID_1080P_60HZ			0x0004
+#define PS3AV_CMD_AV_VID_576I				0x0005
+#define PS3AV_CMD_AV_VID_576P				0x0006
+#define PS3AV_CMD_AV_VID_720P_50HZ			0x0007
+#define PS3AV_CMD_AV_VID_1080I_50HZ			0x0008
+#define PS3AV_CMD_AV_VID_1080P_50HZ			0x0009
+#define PS3AV_CMD_AV_VID_WXGA				0x000a
+#define PS3AV_CMD_AV_VID_SXGA				0x000b
+#define PS3AV_CMD_AV_VID_WUXGA				0x000c
+/* av_cs_out av_cs_in */
+/* use cs_video2av() */
+#define PS3AV_CMD_AV_CS_RGB_8				0x0000
+#define PS3AV_CMD_AV_CS_YUV444_8			0x0001
+#define PS3AV_CMD_AV_CS_YUV422_8			0x0002
+#define PS3AV_CMD_AV_CS_XVYCC_8				0x0003
+#define PS3AV_CMD_AV_CS_RGB_10				0x0004
+#define PS3AV_CMD_AV_CS_YUV444_10			0x0005
+#define PS3AV_CMD_AV_CS_YUV422_10			0x0006
+#define PS3AV_CMD_AV_CS_XVYCC_10			0x0007
+#define PS3AV_CMD_AV_CS_RGB_12				0x0008
+#define PS3AV_CMD_AV_CS_YUV444_12			0x0009
+#define PS3AV_CMD_AV_CS_YUV422_12			0x000a
+#define PS3AV_CMD_AV_CS_XVYCC_12			0x000b
+#define PS3AV_CMD_AV_CS_8				0x0000
+#define PS3AV_CMD_AV_CS_10				0x0001
+#define PS3AV_CMD_AV_CS_12				0x0002
+/* dither */
+#define PS3AV_CMD_AV_DITHER_OFF				0x0000
+#define PS3AV_CMD_AV_DITHER_ON				0x0001
+#define PS3AV_CMD_AV_DITHER_8BIT			0x0000
+#define PS3AV_CMD_AV_DITHER_10BIT			0x0002
+#define PS3AV_CMD_AV_DITHER_12BIT			0x0004
+/* super_white */
+#define PS3AV_CMD_AV_SUPER_WHITE_OFF			0x0000
+#define PS3AV_CMD_AV_SUPER_WHITE_ON			0x0001
+/* aspect */
+#define PS3AV_CMD_AV_ASPECT_16_9			0x0000
+#define PS3AV_CMD_AV_ASPECT_4_3				0x0001
+/* video_cs_cnv() */
+#define PS3AV_CMD_VIDEO_CS_RGB				0x0001
+#define PS3AV_CMD_VIDEO_CS_YUV422			0x0002
+#define PS3AV_CMD_VIDEO_CS_YUV444			0x0003
+
+/* for automode */
+#define PS3AV_RESBIT_720x480P			0x0003	/* 0x0001 | 0x0002 */
+#define PS3AV_RESBIT_720x576P			0x0003	/* 0x0001 | 0x0002 */
+#define PS3AV_RESBIT_1280x720P			0x0004
+#define PS3AV_RESBIT_1920x1080I			0x0008
+#define PS3AV_RESBIT_1920x1080P			0x4000
+#define PS3AV_RES_MASK_60			(PS3AV_RESBIT_720x480P \
+						| PS3AV_RESBIT_1280x720P \
+						| PS3AV_RESBIT_1920x1080I \
+						| PS3AV_RESBIT_1920x1080P)
+#define PS3AV_RES_MASK_50			(PS3AV_RESBIT_720x576P \
+						| PS3AV_RESBIT_1280x720P \
+						| PS3AV_RESBIT_1920x1080I \
+						| PS3AV_RESBIT_1920x1080P)
+
+#define PS3AV_MONITOR_TYPE_HDMI			1	/* HDMI */
+#define PS3AV_MONITOR_TYPE_DVI			2	/* DVI */
+#define PS3AV_DEFAULT_HDMI_VID_REG_60		PS3AV_CMD_VIDEO_VID_480P
+#define PS3AV_DEFAULT_AVMULTI_VID_REG_60	PS3AV_CMD_VIDEO_VID_480I
+#define PS3AV_DEFAULT_HDMI_VID_REG_50		PS3AV_CMD_VIDEO_VID_576P
+#define PS3AV_DEFAULT_AVMULTI_VID_REG_50	PS3AV_CMD_VIDEO_VID_576I
+#define PS3AV_DEFAULT_DVI_VID			PS3AV_CMD_VIDEO_VID_480P
+
+#define PS3AV_REGION_60				0x01
+#define PS3AV_REGION_50				0x02
+#define PS3AV_REGION_RGB			0x10
+
+#define get_status(buf)				(((__u32 *)buf)[2])
+#define PS3AV_HDR_SIZE				4	/* version + size */
+
+/* for video mode */
+#define PS3AV_MODE_MASK				0x000F
+#define PS3AV_MODE_HDCP_OFF			0x1000	/* Retail PS3 product doesn't support this */
+#define PS3AV_MODE_DITHER			0x0800
+#define PS3AV_MODE_FULL				0x0080
+#define PS3AV_MODE_DVI				0x0040
+#define PS3AV_MODE_RGB				0x0020
+
+
+/** command packet structure **/
+struct ps3av_send_hdr {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+};
+
+struct ps3av_reply_hdr {
+	u16 version;
+	u16 size;
+	u32 cid;
+	u32 status;
+};
+
+/* backend: initialization */
+struct ps3av_pkt_av_init {
+	struct ps3av_send_hdr send_hdr;
+	u32 event_bit;
+};
+
+/* backend: finalize */
+struct ps3av_pkt_av_fin {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* backend: get port */
+struct ps3av_pkt_av_get_hw_conf {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 status;
+	u16 num_of_hdmi;	/* out: number of hdmi */
+	u16 num_of_avmulti;	/* out: number of avmulti */
+	u16 num_of_spdif;	/* out: number of hdmi */
+	u16 reserved;
+};
+
+/* backend: get monitor info */
+struct ps3av_info_resolution {
+	u32 res_bits;
+	u32 native;
+};
+
+struct ps3av_info_cs {
+	u8 rgb;
+	u8 yuv444;
+	u8 yuv422;
+	u8 reserved;
+};
+
+struct ps3av_info_color {
+	u16 red_x;
+	u16 red_y;
+	u16 green_x;
+	u16 green_y;
+	u16 blue_x;
+	u16 blue_y;
+	u16 white_x;
+	u16 white_y;
+	u32 gamma;
+};
+
+struct ps3av_info_audio {
+	u8 type;
+	u8 max_num_of_ch;
+	u8 fs;
+	u8 sbit;
+};
+
+struct ps3av_info_monitor {
+	u8 avport;
+	u8 monitor_id[10];
+	u8 monitor_type;
+	u8 monitor_name[16];
+	struct ps3av_info_resolution res_60;
+	struct ps3av_info_resolution res_50;
+	struct ps3av_info_resolution res_other;
+	struct ps3av_info_resolution res_vesa;
+	struct ps3av_info_cs cs;
+	struct ps3av_info_color color;
+	u8 supported_ai;
+	u8 speaker_info;
+	u8 num_of_audio_block;
+	struct ps3av_info_audio audio[0];	/* 0 or more audio blocks */
+	u8 reserved[169];
+} __attribute__ ((packed));
+
+struct ps3av_pkt_av_get_monitor_info {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+	/* recv */
+	struct ps3av_info_monitor info;	/* out: monitor info */
+};
+
+/* backend: enable/disable event */
+struct ps3av_pkt_av_event {
+	struct ps3av_send_hdr send_hdr;
+	u32 event_bit;		/* in */
+};
+
+/* backend: video cs param */
+struct ps3av_pkt_av_video_cs {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 av_vid;		/* in: video resolution */
+	u16 av_cs_out;		/* in: output color space */
+	u16 av_cs_in;		/* in: input color space */
+	u8 dither;		/* in: dither bit length */
+	u8 bitlen_out;		/* in: bit length */
+	u8 super_white;		/* in: super white */
+	u8 aspect;		/* in: aspect ratio */
+};
+
+/* backend: video mute */
+struct ps3av_av_mute {
+	u16 avport;		/* in: avport */
+	u16 mute;		/* in: mute on/off */
+};
+
+struct ps3av_pkt_av_video_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
+};
+
+/* backend: video disable signal */
+struct ps3av_pkt_av_video_disable_sig {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+};
+
+/* backend: audio param */
+struct ps3av_audio_info_frame {
+	struct pb1_bit {
+		u8 ct:4;
+		u8 rsv:1;
+		u8 cc:3;
+	} pb1;
+	struct pb2_bit {
+		u8 rsv:3;
+		u8 sf:3;
+		u8 ss:2;
+	} pb2;
+	u8 pb3;
+	u8 pb4;
+	struct pb5_bit {
+		u8 dm:1;
+		u8 lsv:4;
+		u8 rsv:3;
+	} pb5;
+};
+
+struct ps3av_pkt_av_audio_param {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport */
+	u16 reserved;
+	u8 mclk;		/* in: audio mclk */
+	u8 ns[3];		/* in: audio ns val */
+	u8 enable;		/* in: audio enable */
+	u8 swaplr;		/* in: audio swap */
+	u8 fifomap;		/* in: audio fifomap */
+	u8 inputctrl;		/* in: audio input ctrl */
+	u8 inputlen;		/* in: sample bit size */
+	u8 layout;		/* in: speaker layout param */
+	struct ps3av_audio_info_frame info;	/* in: info */
+	u8 chstat[5];		/* in: ch stat */
+};
+
+/* backend: audio_mute */
+struct ps3av_pkt_av_audio_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX];
+};
+
+/* backend: hdmi_mode */
+struct ps3av_pkt_av_hdmi_mode {
+	struct ps3av_send_hdr send_hdr;
+	u8 mode;		/* in: hdmi_mode */
+	u8 reserved0;
+	u8 reserved1;
+	u8 reserved2;
+};
+
+/* backend: tv_mute */
+struct ps3av_pkt_av_tv_mute {
+	struct ps3av_send_hdr send_hdr;
+	u16 avport;		/* in: avport HDMI only */
+	u16 mute;		/* in: mute */
+};
+
+/* video: initialize */
+struct ps3av_pkt_video_init {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* video: mode setting */
+struct ps3av_pkt_video_mode {
+	struct ps3av_send_hdr send_hdr;
+	u32 video_head;		/* in: head */
+	u32 reserved;
+	u32 video_vid;		/* in: video resolution */
+	u16 reserved1;
+	u16 width;		/* in: width in pixel */
+	u16 reserved2;
+	u16 height;		/* in: height in pixel */
+	u32 pitch;		/* in: line size in byte */
+	u32 video_out_format;	/* in: out format */
+	u32 video_format;	/* in: input frame buffer format */
+	u8 reserved3;
+	u8 reserved4;
+	u16 video_order;	/* in: input RGB order */
+	u32 reserved5;
+};
+
+/* video: format */
+struct ps3av_pkt_video_format {
+	struct ps3av_send_hdr send_hdr;
+	u32 video_head;		/* in: head */
+	u32 video_format;	/* in: frame buffer format */
+	u16 reserved;
+	u16 video_order;	/* in: input RGB order */
+};
+
+/* video: pitch */
+struct ps3av_pkt_video_pitch {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u32 video_head;		/* in: head */
+	u32 pitch;		/* in: line size in byte */
+};
+
+/* audio: initialize */
+struct ps3av_pkt_audio_init {
+	struct ps3av_send_hdr send_hdr;
+	/* recv */
+	u32 reserved;
+};
+
+/* audio: mode setting */
+struct ps3av_pkt_audio_mode {
+	struct ps3av_send_hdr send_hdr;
+	u8 avport;		/* in: avport */
+	u8 reserved0[3];
+	u32 mask;		/* in: mask */
+	u32 audio_num_of_ch;	/* in: number of ch */
+	u32 audio_fs;		/* in: sampling freq */
+	u32 audio_word_bits;	/* in: sample bit size */
+	u32 audio_format;	/* in: audio output format */
+	u32 audio_source;	/* in: audio source */
+	u8 audio_enable[4];	/* in: audio enable */
+	u8 audio_swap[4];	/* in: audio swap */
+	u8 audio_map[4];	/* in: audio map */
+	u32 audio_layout;	/* in: speaker layout */
+	u32 audio_downmix;	/* in: audio downmix permission */
+	u32 audio_downmix_level;
+	u8 audio_cs_info[8];	/* in: IEC channel status */
+};
+
+/* audio: mute */
+struct ps3av_audio_mute {
+	u8 avport;		/* in: opt_port optical */
+	u8 reserved[3];
+	u32 mute;		/* in: mute */
+};
+
+struct ps3av_pkt_audio_mute {
+	struct ps3av_send_hdr send_hdr;
+	struct ps3av_audio_mute mute[PS3AV_OPT_PORT_MAX];
+};
+
+/* audio: active/inactive */
+struct ps3av_pkt_audio_active {
+	struct ps3av_send_hdr send_hdr;
+	u32 audio_port;		/* in: audio active/inactive port */
+};
+
+/* audio: SPDIF user bit */
+struct ps3av_pkt_audio_spdif_bit {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u8 avport;		/* in: avport SPDIF only */
+	u8 reserved[3];
+	u32 audio_port;		/* in: SPDIF only */
+	u32 spdif_bit_data[12];	/* in: user bit data */
+};
+
+/* audio: audio control */
+struct ps3av_pkt_audio_ctrl {
+	u16 version;
+	u16 size;		/* size of command packet */
+	u32 cid;		/* command id */
+	u32 audio_ctrl_id;	/* in: control id */
+	u32 audio_ctrl_data[4];	/* in: control data */
+};
+
+/* avb:param */
+#define PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE	\
+	(PS3AV_AVB_NUM_VIDEO*sizeof(struct ps3av_pkt_video_mode) + \
+	 PS3AV_AVB_NUM_AUDIO*sizeof(struct ps3av_pkt_audio_mode) + \
+	 PS3AV_AVB_NUM_AV_VIDEO*sizeof(struct ps3av_pkt_av_video_cs) + \
+	 PS3AV_AVB_NUM_AV_AUDIO*sizeof(struct ps3av_pkt_av_audio_param))
+
+struct ps3av_pkt_avb_param {
+	struct ps3av_send_hdr send_hdr;
+	u16 num_of_video_pkt;
+	u16 num_of_audio_pkt;
+	u16 num_of_av_video_pkt;
+	u16 num_of_av_audio_pkt;
+	/*
+	 * The actual buffer layout depends on the fields above:
+	 *
+	 * struct ps3av_pkt_video_mode video[num_of_video_pkt];
+	 * struct ps3av_pkt_audio_mode audio[num_of_audio_pkt];
+	 * struct ps3av_pkt_av_video_cs av_video[num_of_av_video_pkt];
+	 * struct ps3av_pkt_av_audio_param av_audio[num_of_av_audio_pkt];
+	 */
+	u8 buf[PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE];
+};
+
+struct ps3av {
+	int available;
+	struct semaphore sem;
+	struct semaphore ping;
+	struct semaphore pong;
+	struct mutex mutex;
+	int open_count;
+	struct ps3_vuart_port_device *dev;
+
+	int region;
+	struct ps3av_pkt_av_get_hw_conf av_hw_conf;
+	u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX];
+	u32 opt_port[PS3AV_OPT_PORT_MAX];
+	u32 head[PS3AV_HEAD_MAX];
+	u32 audio_port;
+	int ps3av_mode;
+	int ps3av_mode_old;
+};
+
+/** command status **/
+#define PS3AV_STATUS_SUCCESS			0x0000	/* success */
+#define PS3AV_STATUS_RECEIVE_VUART_ERROR	0x0001	/* receive vuart error */
+#define PS3AV_STATUS_SYSCON_COMMUNICATE_FAIL	0x0002	/* syscon communication error */
+#define PS3AV_STATUS_INVALID_COMMAND		0x0003	/* obsolete invalid CID */
+#define PS3AV_STATUS_INVALID_PORT		0x0004	/* invalid port number */
+#define PS3AV_STATUS_INVALID_VID		0x0005	/* invalid video format */
+#define PS3AV_STATUS_INVALID_COLOR_SPACE	0x0006	/* invalid video colose space */
+#define PS3AV_STATUS_INVALID_FS			0x0007	/* invalid audio sampling freq */
+#define PS3AV_STATUS_INVALID_AUDIO_CH		0x0008	/* invalid audio channel number */
+#define PS3AV_STATUS_UNSUPPORTED_VERSION	0x0009	/* version mismatch  */
+#define PS3AV_STATUS_INVALID_SAMPLE_SIZE	0x000a	/* invalid audio sample bit size */
+#define PS3AV_STATUS_FAILURE			0x000b	/* other failures */
+#define PS3AV_STATUS_UNSUPPORTED_COMMAND	0x000c	/* unsupported cid */
+#define PS3AV_STATUS_BUFFER_OVERFLOW		0x000d	/* write buffer overflow */
+#define PS3AV_STATUS_INVALID_VIDEO_PARAM	0x000e	/* invalid video param */
+#define PS3AV_STATUS_NO_SEL			0x000f	/* not exist selector */
+#define PS3AV_STATUS_INVALID_AV_PARAM		0x0010	/* invalid backend param */
+#define PS3AV_STATUS_INVALID_AUDIO_PARAM	0x0011	/* invalid audio param */
+#define PS3AV_STATUS_UNSUPPORTED_HDMI_MODE	0x0012	/* unsupported hdmi mode */
+#define PS3AV_STATUS_NO_SYNC_HEAD		0x0013	/* sync head failed */
+
+extern void ps3av_set_hdr(u32, u16, struct ps3av_send_hdr *);
+extern int ps3av_do_pkt(u32, u16, size_t, struct ps3av_send_hdr *);
+
+extern int ps3av_cmd_init(void);
+extern int ps3av_cmd_fin(void);
+extern int ps3av_cmd_av_video_mute(int, u32 *, u32);
+extern int ps3av_cmd_av_video_disable_sig(u32);
+extern int ps3av_cmd_av_tv_mute(u32, u32);
+extern int ps3av_cmd_enable_event(void);
+extern int ps3av_cmd_av_hdmi_mode(u8);
+extern u32 ps3av_cmd_set_av_video_cs(void *, u32, int, int, int, u32);
+extern u32 ps3av_cmd_set_video_mode(void *, u32, int, int, u32);
+extern int ps3av_cmd_video_format_black(u32, u32, u32);
+extern int ps3av_cmd_av_audio_mute(int, u32 *, u32);
+extern u32 ps3av_cmd_set_av_audio_param(void *, u32,
+					const struct ps3av_pkt_audio_mode *,
+					u32);
+extern void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *, u32, u32,
+				     u32, u32, u32, u32);
+extern int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *);
+extern int ps3av_cmd_audio_mute(int, u32 *, u32);
+extern int ps3av_cmd_audio_active(int, u32);
+extern int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *, u32);
+extern int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *);
+#ifdef PS3AV_DEBUG
+extern void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *);
+extern void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *);
+#else
+static inline void ps3av_cmd_av_hw_conf_dump(const struct ps3av_pkt_av_get_hw_conf *hw_conf) {}
+static inline void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) {}
+#endif
+extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *,
+					    u32);
+
+extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev,
+			     const void *buf, unsigned long size);
+extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf,
+			    unsigned long size, int timeout);
+
+extern int ps3av_set_video_mode(u32, int);
+extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
+extern int ps3av_set_mode(u32, int);
+extern int ps3av_get_mode(void);
+extern int ps3av_get_scanmode(int);
+extern int ps3av_get_refresh_rate(int);
+extern int ps3av_video_mode2res(u32, u32 *, u32 *);
+extern int ps3av_video_mute(int);
+extern int ps3av_audio_mute(int);
+extern int ps3av_dev_open(void);
+extern int ps3av_dev_close(void);
+
+#endif	/* _ASM_POWERPC_PS3AV_H_ */
diff --git a/include/asm-powerpc/ps3fb.h b/include/asm-powerpc/ps3fb.h
new file mode 100644
index 0000000..ad81cf4
--- /dev/null
+++ b/include/asm-powerpc/ps3fb.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2006 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * 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 of the License.
+ *
+ * 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.
+ */
+
+#ifndef _ASM_POWERPC_PS3FB_H_
+#define _ASM_POWERPC_PS3FB_H_
+
+#include <linux/ioctl.h>
+
+/* ioctl */
+#define PS3FB_IOCTL_SETMODE       _IOW('r',  1, int) /* set video mode */
+#define PS3FB_IOCTL_GETMODE       _IOR('r',  2, int) /* get video mode */
+#define PS3FB_IOCTL_SCREENINFO    _IOR('r',  3, int) /* get screen info */
+#define PS3FB_IOCTL_ON            _IO('r', 4)        /* use IOCTL_FSEL */
+#define PS3FB_IOCTL_OFF           _IO('r', 5)        /* return to normal-flip */
+#define PS3FB_IOCTL_FSEL          _IOW('r', 6, int)  /* blit and flip request */
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC         _IOW('F', 0x20, __u32) /* wait for vsync */
+#endif
+
+struct ps3fb_ioctl_res {
+	__u32 xres; /* frame buffer x_size */
+	__u32 yres; /* frame buffer y_size */
+	__u32 xoff; /* margine x  */
+	__u32 yoff; /* margine y */
+	__u32 num_frames; /* num of frame buffers */
+};
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_FB_PS3
+extern void ps3fb_flip_ctl(int on);
+extern void ps3fb_cleanup(void);
+#else
+static inline void ps3fb_flip_ctl(int on) {}
+static inline void ps3fb_cleanup(void) {}
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_POWERPC_PS3FB_H_ */
diff --git a/include/asm-x86_64/bootsetup.h b/include/asm-x86_64/bootsetup.h
index b829f7b..7b1c3ad 100644
--- a/include/asm-x86_64/bootsetup.h
+++ b/include/asm-x86_64/bootsetup.h
@@ -31,7 +31,7 @@
 #define EDD_MBR_SIG_NR (*(unsigned char *) (PARAM+EDD_MBR_SIG_NR_BUF))
 #define EDD_MBR_SIGNATURE ((unsigned int *) (PARAM+EDD_MBR_SIG_BUF))
 #define EDD_BUF     ((struct edd_info *) (PARAM+EDDBUF))
-#define COMMAND_LINE saved_command_line
+#define COMMAND_LINE boot_command_line
 
 #define RAMDISK_IMAGE_START_MASK  	0x07FF
 #define RAMDISK_PROMPT_FLAG		0x8000
diff --git a/include/asm-x86_64/setup.h b/include/asm-x86_64/setup.h
index 985d4e3..eaeff73 100644
--- a/include/asm-x86_64/setup.h
+++ b/include/asm-x86_64/setup.h
@@ -1,6 +1,6 @@
 #ifndef _x8664_SETUP_H
 #define _x8664_SETUP_H
 
-#define COMMAND_LINE_SIZE	256
+#define COMMAND_LINE_SIZE	2048
 
 #endif
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index bb881c3..e81e301 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -323,6 +323,7 @@
 unifdef-y += types.h
 unifdef-y += udf_fs_i.h
 unifdef-y += udp.h
+unifdef-y += ufs_fs.h
 unifdef-y += uinput.h
 unifdef-y += uio.h
 unifdef-y += unistd.h
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 75b8bac..d12984d 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -182,7 +182,7 @@
 
 extern struct atalk_route atrtr_default;
 
-extern struct file_operations atalk_seq_arp_fops;
+extern const struct file_operations atalk_seq_arp_fops;
 
 extern int sysctl_aarp_expiry_time;
 extern int sysctl_aarp_tick_time;
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 5d9fb0e..dd27b1c 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -34,6 +34,7 @@
 	BH_Write_EIO,	/* I/O error on write */
 	BH_Ordered,	/* ordered write */
 	BH_Eopnotsupp,	/* operation not supported (barrier) */
+	BH_Unwritten,	/* Buffer is allocated on disk but not written */
 
 	BH_PrivateStart,/* not a state bit, but the first bit available
 			 * for private allocation by other entities
@@ -126,6 +127,7 @@
 BUFFER_FNS(Write_EIO, write_io_error)
 BUFFER_FNS(Ordered, ordered)
 BUFFER_FNS(Eopnotsupp, eopnotsupp)
+BUFFER_FNS(Unwritten, unwritten)
 
 #define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
 #define touch_buffer(bh)	mark_page_accessed(bh->b_page)
@@ -172,12 +174,14 @@
 void thaw_bdev(struct block_device *, struct super_block *);
 int fsync_super(struct super_block *);
 int fsync_no_super(struct block_device *);
-struct buffer_head *__find_get_block(struct block_device *, sector_t, int);
-struct buffer_head * __getblk(struct block_device *, sector_t, int);
+struct buffer_head *__find_get_block(struct block_device *bdev, sector_t block,
+			unsigned size);
+struct buffer_head *__getblk(struct block_device *bdev, sector_t block,
+			unsigned size);
 void __brelse(struct buffer_head *);
 void __bforget(struct buffer_head *);
-void __breadahead(struct block_device *, sector_t block, int size);
-struct buffer_head *__bread(struct block_device *, sector_t block, int size);
+void __breadahead(struct block_device *, sector_t block, unsigned int size);
+struct buffer_head *__bread(struct block_device *, sector_t block, unsigned size);
 struct buffer_head *alloc_buffer_head(gfp_t gfp_flags);
 void free_buffer_head(struct buffer_head * bh);
 void FASTCALL(unlock_buffer(struct buffer_head *bh));
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index 4c2632a..e4ac016 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -23,9 +23,9 @@
 #include <linux/coda_fs_i.h>
 
 /* operations */
-extern struct inode_operations coda_dir_inode_operations;
-extern struct inode_operations coda_file_inode_operations;
-extern struct inode_operations coda_ioctl_inode_operations;
+extern const struct inode_operations coda_dir_inode_operations;
+extern const struct inode_operations coda_file_inode_operations;
+extern const struct inode_operations coda_ioctl_inode_operations;
 
 extern const struct address_space_operations coda_file_aops;
 extern const struct address_space_operations coda_symlink_aops;
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index bfb5202..769ddc6 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -49,10 +49,20 @@
 
 #ifdef CONFIG_SMP
 /* Need to know about CPUs going up/down? */
-extern int register_cpu_notifier(struct notifier_block *nb);
 #ifdef CONFIG_HOTPLUG_CPU
+extern int register_cpu_notifier(struct notifier_block *nb);
 extern void unregister_cpu_notifier(struct notifier_block *nb);
 #else
+
+#ifndef MODULE
+extern int register_cpu_notifier(struct notifier_block *nb);
+#else
+static inline int register_cpu_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+#endif
+
 static inline void unregister_cpu_notifier(struct notifier_block *nb)
 {
 }
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index fd40441..826b15e 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -55,7 +55,7 @@
 extern int cpuset_memory_pressure_enabled;
 extern void __cpuset_memory_pressure_bump(void);
 
-extern struct file_operations proc_cpuset_operations;
+extern const struct file_operations proc_cpuset_operations;
 extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
 
 extern void cpuset_lock(void);
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index 278ef44..dfed800 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -36,7 +36,7 @@
 
 struct statfs;
 
-extern struct inode_operations efs_dir_inode_operations;
+extern const struct inode_operations efs_dir_inode_operations;
 extern const struct file_operations efs_dir_operations;
 extern const struct address_space_operations efs_symlink_aops;
 
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 11cca1b..4eb18ac 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -868,16 +868,16 @@
 extern const struct file_operations ext3_dir_operations;
 
 /* file.c */
-extern struct inode_operations ext3_file_inode_operations;
+extern const struct inode_operations ext3_file_inode_operations;
 extern const struct file_operations ext3_file_operations;
 
 /* namei.c */
-extern struct inode_operations ext3_dir_inode_operations;
-extern struct inode_operations ext3_special_inode_operations;
+extern const struct inode_operations ext3_dir_inode_operations;
+extern const struct inode_operations ext3_special_inode_operations;
 
 /* symlink.c */
-extern struct inode_operations ext3_symlink_inode_operations;
-extern struct inode_operations ext3_fast_symlink_inode_operations;
+extern const struct inode_operations ext3_symlink_inode_operations;
+extern const struct inode_operations ext3_fast_symlink_inode_operations;
 
 
 #endif	/* __KERNEL__ */
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index 498503e..54c576d 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -955,16 +955,16 @@
 extern const struct file_operations ext4_dir_operations;
 
 /* file.c */
-extern struct inode_operations ext4_file_inode_operations;
+extern const struct inode_operations ext4_file_inode_operations;
 extern const struct file_operations ext4_file_operations;
 
 /* namei.c */
-extern struct inode_operations ext4_dir_inode_operations;
-extern struct inode_operations ext4_special_inode_operations;
+extern const struct inode_operations ext4_dir_inode_operations;
+extern const struct inode_operations ext4_special_inode_operations;
 
 /* symlink.c */
-extern struct inode_operations ext4_symlink_inode_operations;
-extern struct inode_operations ext4_fast_symlink_inode_operations;
+extern const struct inode_operations ext4_symlink_inode_operations;
+extern const struct inode_operations ext4_fast_symlink_inode_operations;
 
 /* extents.c */
 extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 64177ec..a78e256 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -49,6 +49,13 @@
 #define FB_AUX_TEXT_S3_MMIO	2	/* S3 MMIO fasttext */
 #define FB_AUX_TEXT_MGA_STEP16	3	/* MGA Millenium I: text, attr, 14 reserved bytes */
 #define FB_AUX_TEXT_MGA_STEP8	4	/* other MGAs:      text, attr,  6 reserved bytes */
+#define FB_AUX_TEXT_SVGA_GROUP	8	/* 8-15: SVGA tileblit compatible modes */
+#define FB_AUX_TEXT_SVGA_MASK	7	/* lower three bits says step */
+#define FB_AUX_TEXT_SVGA_STEP2	8	/* SVGA text mode:  text, attr */
+#define FB_AUX_TEXT_SVGA_STEP4	9	/* SVGA text mode:  text, attr,  2 reserved bytes */
+#define FB_AUX_TEXT_SVGA_STEP8	10	/* SVGA text mode:  text, attr,  6 reserved bytes */
+#define FB_AUX_TEXT_SVGA_STEP16	11	/* SVGA text mode:  text, attr, 14 reserved bytes */
+#define FB_AUX_TEXT_SVGA_LAST	15	/* reserved up to 15 */
 
 #define FB_AUX_VGA_PLANES_VGA4		0	/* 16 color planes (EGA/VGA) */
 #define FB_AUX_VGA_PLANES_CFB4		1	/* CFB4 in planes (VGA) */
@@ -945,25 +952,26 @@
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
 extern void fb_var_to_videomode(struct fb_videomode *mode,
-				struct fb_var_screeninfo *var);
+				const struct fb_var_screeninfo *var);
 extern void fb_videomode_to_var(struct fb_var_screeninfo *var,
-				struct fb_videomode *mode);
-extern int fb_mode_is_equal(struct fb_videomode *mode1,
-			    struct fb_videomode *mode2);
-extern int fb_add_videomode(struct fb_videomode *mode, struct list_head *head);
-extern void fb_delete_videomode(struct fb_videomode *mode,
+				const struct fb_videomode *mode);
+extern int fb_mode_is_equal(const struct fb_videomode *mode1,
+			    const struct fb_videomode *mode2);
+extern int fb_add_videomode(const struct fb_videomode *mode,
+			    struct list_head *head);
+extern void fb_delete_videomode(const struct fb_videomode *mode,
 				struct list_head *head);
-extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
-					  struct list_head *head);
-extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
-					      struct list_head *head);
-extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
-						 struct list_head *head);
+extern const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var,
+						struct list_head *head);
+extern const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var,
+						    struct list_head *head);
+extern const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode,
+						       struct list_head *head);
 extern void fb_destroy_modelist(struct list_head *head);
-extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+extern void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num,
 				     struct list_head *head);
-extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
-						 struct list_head *head);
+extern const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs,
+						       struct list_head *head);
 
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 20fd161..86ec3f4 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -551,7 +551,7 @@
 	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
 	struct mutex		i_mutex;
 	struct rw_semaphore	i_alloc_sem;
-	struct inode_operations	*i_op;
+	const struct inode_operations	*i_op;
 	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
 	struct super_block	*i_sb;
 	struct file_lock	*i_flock;
@@ -907,7 +907,7 @@
 	unsigned char		s_dirt;
 	unsigned long long	s_maxbytes;	/* Max file size */
 	struct file_system_type	*s_type;
-	struct super_operations	*s_op;
+	const struct super_operations	*s_op;
 	struct dquot_operations	*dq_op;
  	struct quotactl_ops	*s_qcop;
 	struct export_operations *s_export_op;
@@ -1383,7 +1383,7 @@
 			int (*set)(struct super_block *,void *),
 			void *data);
 extern int get_sb_pseudo(struct file_system_type *, char *,
-	struct super_operations *ops, unsigned long,
+	const struct super_operations *ops, unsigned long,
 	struct vfsmount *mnt);
 extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
 int __put_super(struct super_block *sb);
@@ -1688,7 +1688,6 @@
 extern int __remove_suid(struct dentry *, int);
 extern int should_remove_suid(struct dentry *);
 extern int remove_suid(struct dentry *);
-extern void remove_dquot_ref(struct super_block *, int, struct list_head *);
 
 extern void __insert_inode_hash(struct inode *, unsigned long hashval);
 extern void remove_inode_hash(struct inode *);
@@ -1829,7 +1828,7 @@
 extern int __page_symlink(struct inode *inode, const char *symname, int len,
 		gfp_t gfp_mask);
 extern int page_symlink(struct inode *inode, const char *symname, int len);
-extern struct inode_operations page_symlink_inode_operations;
+extern const struct inode_operations page_symlink_inode_operations;
 extern int generic_readlink(struct dentry *, char __user *, int);
 extern void generic_fillattr(struct inode *, struct kstat *);
 extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
@@ -1874,7 +1873,7 @@
 extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
 extern const struct file_operations simple_dir_operations;
-extern struct inode_operations simple_dir_inode_operations;
+extern const struct inode_operations simple_dir_inode_operations;
 struct tree_descr { char *name; const struct file_operations *ops; int mode; };
 struct dentry *d_alloc_name(struct dentry *, const char *);
 extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
diff --git a/include/linux/gigaset_dev.h b/include/linux/gigaset_dev.h
index 70ad09c..5dc4a31 100644
--- a/include/linux/gigaset_dev.h
+++ b/include/linux/gigaset_dev.h
@@ -9,8 +9,6 @@
  *    published by the Free Software Foundation; either version 2 of
  *    the License, or (at your option) any later version.
  * =====================================================================
- * Version: $Id: gigaset_dev.h,v 1.4.4.4 2005/11/21 22:28:09 hjlipp Exp $
- * =====================================================================
  */
 
 #ifndef GIGASET_INTERFACE_H
diff --git a/include/linux/init.h b/include/linux/init.h
index c65f510..e290a01 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -67,7 +67,8 @@
 extern initcall_t __security_initcall_start[], __security_initcall_end[];
 
 /* Defined in init/main.c */
-extern char saved_command_line[];
+extern char __initdata boot_command_line[];
+extern char *saved_command_line;
 extern unsigned int reset_devices;
 
 /* used by init/main.c */
@@ -164,7 +165,7 @@
 #define early_param(str, fn)					\
 	__setup_param(str, fn, fn, 1)
 
-/* Relies on saved_command_line being set */
+/* Relies on boot_command_line being set */
 void __init parse_early_param(void);
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 6383d2d..a2d95ff 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -66,7 +66,7 @@
 	.cpu_timers	= INIT_CPU_TIMERS(sig.cpu_timers),		\
 	.rlim		= INIT_RLIMITS,					\
 	.pgrp		= 1,						\
-	.tty_old_pgrp   = 0,						\
+	.tty_old_pgrp   = NULL,						\
 	{ .__session      = 1},						\
 }
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e91dce7..9ddf25c 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -92,11 +92,6 @@
 		(__x < 0) ? -__x : __x;		\
 	})
 
-#define labs(x) ({				\
-		long __x = (x);			\
-		(__x < 0) ? -__x : __x;		\
-	})
-
 extern struct atomic_notifier_head panic_notifier_list;
 extern long (*panic_blink)(long time);
 NORET_TYPE void panic(const char * fmt, ...)
@@ -139,7 +134,8 @@
 extern int core_kernel_text(unsigned long addr);
 extern int __kernel_text_address(unsigned long addr);
 extern int kernel_text_address(unsigned long addr);
-extern int session_of_pgrp(int pgrp);
+struct pid;
+extern struct pid *session_of_pgrp(struct pid *pgrp);
 
 extern void dump_thread(struct pt_regs *regs, struct user *dump);
 
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 1be148f..f360459 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -11,7 +11,7 @@
 #include <asm/types.h>
 #include <linux/ioctl.h>
 
-#define KVM_API_VERSION 2
+#define KVM_API_VERSION 3
 
 /*
  * Architectural interrupt line count, and the size of the bitmap needed
@@ -65,6 +65,8 @@
 	__u8 ready_for_interrupt_injection;
 	__u8 if_flag;
 	__u16 padding2;
+
+	/* in (pre_kvm_run), out (post_kvm_run) */
 	__u64 cr8;
 	__u64 apic_base;
 
@@ -185,6 +187,7 @@
 	__u8  valid;
 	__u8  writeable;
 	__u8  usermode;
+	__u8  pad[5];
 };
 
 /* for KVM_INTERRUPT */
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 7e1160d..06fe93a 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -8,6 +8,8 @@
 #ifndef __LINUX_LOCKDEP_H
 #define __LINUX_LOCKDEP_H
 
+struct task_struct;
+
 #ifdef CONFIG_LOCKDEP
 
 #include <linux/linkage.h>
diff --git a/include/linux/magic.h b/include/linux/magic.h
index b78bbf4..b32c8a9 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -18,6 +18,7 @@
 #define MINIX_SUPER_MAGIC2	0x138F		/* minix fs, 30 char names */
 #define MINIX2_SUPER_MAGIC	0x2468		/* minix V2 fs */
 #define MINIX2_SUPER_MAGIC2	0x2478		/* minix V2 fs, 30 char names */
+#define MINIX3_SUPER_MAGIC	0x4d5a		/* minix V3 fs */
 
 #define MSDOS_SUPER_MAGIC	0x4d44		/* MD */
 #define NCP_SUPER_MAGIC		0x564c		/* Guess, what 0x564c is :-) */
diff --git a/include/linux/minix_fs.h b/include/linux/minix_fs.h
index 916e8f7..9850d51 100644
--- a/include/linux/minix_fs.h
+++ b/include/linux/minix_fs.h
@@ -25,7 +25,6 @@
 #define MINIX_ERROR_FS		0x0002		/* fs has errors. */
 
 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
-#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
 
 /*
  * This is the original minix inode layout on disk.
@@ -75,9 +74,33 @@
 	__u32 s_zones;
 };
 
+/*
+ * V3 minix super-block data on disk
+ */
+struct minix3_super_block {
+	__u16 s_ninodes;
+	__u16 s_nzones;
+	__u16 s_pad0;
+	__u16 s_imap_blocks;
+	__u16 s_zmap_blocks;
+	__u16 s_firstdatazone;
+	__u16 s_log_zone_size;
+	__u16 s_pad1;
+	__u32 s_max_size;
+	__u32 s_zones;
+	__u16 s_magic;
+	__u16 s_pad2;
+	__u16 s_blocksize;
+	__u8  s_disk_version;
+};
+
 struct minix_dir_entry {
 	__u16 inode;
 	char name[0];
 };
 
+struct minix3_dir_entry {
+	__u32 inode;
+	char name[0];
+};
 #endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 77a7610..a0eec16 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -637,6 +637,7 @@
  */
 #define NOPFN_SIGBUS	((unsigned long) -1)
 #define NOPFN_OOM	((unsigned long) -2)
+#define NOPFN_REFAULT	((unsigned long) -3)
 
 /*
  * Different kinds of faults, as returned by handle_mm_fault().
@@ -1124,6 +1125,8 @@
 int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
 			unsigned long pfn, unsigned long size, pgprot_t);
 int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
+int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
+			unsigned long pfn);
 
 struct page *follow_page(struct vm_area_struct *, unsigned long address,
 			unsigned int foll_flags);
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 24a9ef1..fa253fa 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -234,7 +234,7 @@
 	struct fat_mount_options options;
 	struct nls_table *nls_disk;  /* Codepage used on disk */
 	struct nls_table *nls_io;    /* Charset used for input and display */
-	void *dir_ops;		     /* Opaque; default directory operations */
+	const void *dir_ops;		     /* Opaque; default directory operations */
 	int dir_per_block;	     /* dir entries per block */
 	int dir_per_block_bits;	     /* log2(dir_per_block) */
 
@@ -399,7 +399,7 @@
 extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
 			     unsigned int cmd, unsigned long arg);
 extern const struct file_operations fat_file_operations;
-extern struct inode_operations fat_file_inode_operations;
+extern const struct inode_operations fat_file_inode_operations;
 extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
 extern void fat_truncate(struct inode *inode);
 extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
@@ -413,7 +413,7 @@
 			struct msdos_dir_entry *de, loff_t i_pos);
 extern int fat_sync_inode(struct inode *inode);
 extern int fat_fill_super(struct super_block *sb, void *data, int silent,
-			struct inode_operations *fs_dir_inode_ops, int isvfat);
+			const struct inode_operations *fs_dir_inode_ops, int isvfat);
 
 extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
 		            struct inode *i2);
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 0ea7f89..83e39eb 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -204,7 +204,7 @@
 void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
 
 /* linux/fs/ncpfs/dir.c */
-extern struct inode_operations ncp_dir_inode_operations;
+extern const struct inode_operations ncp_dir_inode_operations;
 extern const struct file_operations ncp_dir_operations;
 int ncp_conn_logged_in(struct super_block *);
 int ncp_date_dos2unix(__le16 time, __le16 date);
@@ -226,7 +226,7 @@
 void ncp_unlock_server(struct ncp_server *server);
 
 /* linux/fs/ncpfs/file.c */
-extern struct inode_operations ncp_file_inode_operations;
+extern const struct inode_operations ncp_file_inode_operations;
 extern const struct file_operations ncp_file_operations;
 int ncp_make_open(struct inode *, int);
 
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index b3b9b60..2a20f48 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -23,6 +23,7 @@
 #define NETLINK_GENERIC		16
 /* leave room for NETLINK_DM (DM Events) */
 #define NETLINK_SCSITRANSPORT	18	/* SCSI Transports */
+#define NETLINK_ECRYPTFS	19
 
 #define MAX_LINKS 32		
 
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index c5d4084..ed0f2ea 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -331,9 +331,9 @@
 /*
  * linux/fs/nfs/file.c
  */
-extern struct inode_operations nfs_file_inode_operations;
+extern const struct inode_operations nfs_file_inode_operations;
 #ifdef CONFIG_NFS_V3
-extern struct inode_operations nfs3_file_inode_operations;
+extern const struct inode_operations nfs3_file_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_file_operations;
 extern const struct address_space_operations nfs_file_aops;
@@ -380,9 +380,9 @@
 /*
  * linux/fs/nfs/dir.c
  */
-extern struct inode_operations nfs_dir_inode_operations;
+extern const struct inode_operations nfs_dir_inode_operations;
 #ifdef CONFIG_NFS_V3
-extern struct inode_operations nfs3_dir_inode_operations;
+extern const struct inode_operations nfs3_dir_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_dir_operations;
 extern struct dentry_operations nfs_dentry_operations;
@@ -392,7 +392,7 @@
 /*
  * linux/fs/nfs/symlink.c
  */
-extern struct inode_operations nfs_symlink_inode_operations;
+extern const struct inode_operations nfs_symlink_inode_operations;
 
 /*
  * linux/fs/nfs/sysctl.c
@@ -409,8 +409,8 @@
  * linux/fs/nfs/namespace.c
  */
 extern struct list_head nfs_automount_list;
-extern struct inode_operations nfs_mountpoint_inode_operations;
-extern struct inode_operations nfs_referral_inode_operations;
+extern const struct inode_operations nfs_mountpoint_inode_operations;
+extern const struct inode_operations nfs_referral_inode_operations;
 extern int nfs_mountpoint_expiry_timeout;
 extern void nfs_release_automount_timer(void);
 
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9ee9da5..30d7116 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -767,8 +767,8 @@
 struct nfs_rpc_ops {
 	int	version;		/* Protocol version */
 	struct dentry_operations *dentry_ops;
-	struct inode_operations *dir_inode_ops;
-	struct inode_operations *file_inode_ops;
+	const struct inode_operations *dir_inode_ops;
+	const struct inode_operations *file_inode_ops;
 
 	int	(*getroot) (struct nfs_server *, struct nfs_fh *,
 			    struct nfs_fsinfo *);
diff --git a/include/linux/nfsd/const.h b/include/linux/nfsd/const.h
index f0cc777..323f8cf 100644
--- a/include/linux/nfsd/const.h
+++ b/include/linux/nfsd/const.h
@@ -30,10 +30,6 @@
 
 #include <linux/sunrpc/msg_prot.h>
 
-#ifndef NFS_SUPER_MAGIC
-# define NFS_SUPER_MAGIC	0x6969
-#endif
-
 /*
  * Largest number of bytes we need to allocate for an NFS
  * call or reply.  Used to control buffer sizes.  We use
diff --git a/include/linux/phonedev.h b/include/linux/phonedev.h
index a0e31ad..4269de9 100644
--- a/include/linux/phonedev.h
+++ b/include/linux/phonedev.h
@@ -9,7 +9,7 @@
 
 struct phone_device {
 	struct phone_device *next;
-	struct file_operations *f_op;
+	const struct file_operations *f_op;
 	int (*open) (struct phone_device *, struct file *);
 	int board;		/* Device private index */
 	int minor;
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 4dec047..2ac27f9 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -105,20 +105,6 @@
 	return nr;
 }
 
-
-#define do_each_task_pid(who, type, task)				\
-	do {								\
-		struct hlist_node *pos___;				\
-		struct pid *pid___ = find_pid(who);			\
-		if (pid___ != NULL)					\
-			hlist_for_each_entry_rcu((task), pos___,	\
-				&pid___->tasks[type], pids[type].node) {
-
-#define while_each_task_pid(who, type, task)				\
-			}						\
-	} while (0)
-
-
 #define do_each_pid_task(pid, type, task)				\
 	do {								\
 		struct hlist_node *pos___;				\
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 87dec8f..2e13247 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -55,8 +55,8 @@
 	uid_t uid;
 	gid_t gid;
 	loff_t size;
-	struct inode_operations * proc_iops;
-	const struct file_operations * proc_fops;
+	const struct inode_operations *proc_iops;
+	const struct file_operations *proc_fops;
 	get_info_t *get_info;
 	struct module *owner;
 	struct proc_dir_entry *next, *parent, *subdir;
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
index 0c7ac44..19bc9b8 100644
--- a/include/linux/qnx4_fs.h
+++ b/include/linux/qnx4_fs.h
@@ -116,8 +116,8 @@
 
 extern struct buffer_head *qnx4_bread(struct inode *, int, int);
 
-extern struct inode_operations qnx4_file_inode_operations;
-extern struct inode_operations qnx4_dir_inode_operations;
+extern const struct inode_operations qnx4_file_inode_operations;
+extern const struct inode_operations qnx4_dir_inode_operations;
 extern const struct file_operations qnx4_file_operations;
 extern const struct file_operations qnx4_dir_operations;
 extern int qnx4_is_free(struct super_block *sb, long block);
diff --git a/include/linux/quota.h b/include/linux/quota.h
index b8fbf26..77db80a 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -132,6 +132,7 @@
 
 #ifdef __KERNEL__
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 #include <linux/mutex.h>
 
 #include <linux/dqblk_xfs.h>
diff --git a/include/linux/random.h b/include/linux/random.h
index 01ad710..36f125c 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -63,7 +63,7 @@
 				       __be16 sport, __be16 dport);
 
 #ifndef MODULE
-extern struct file_operations random_fops, urandom_fops;
+extern const struct file_operations random_fops, urandom_fops;
 #endif
 
 unsigned int get_random_int(void);
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index c3fc6ca..965d5b3 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1949,9 +1949,9 @@
 #endif
 
 /* dir.c */
-extern struct inode_operations reiserfs_dir_inode_operations;
-extern struct inode_operations reiserfs_symlink_inode_operations;
-extern struct inode_operations reiserfs_special_inode_operations;
+extern const struct inode_operations reiserfs_dir_inode_operations;
+extern const struct inode_operations reiserfs_symlink_inode_operations;
+extern const struct inode_operations reiserfs_special_inode_operations;
 extern const struct file_operations reiserfs_dir_operations;
 
 /* tail_conversion.c */
@@ -1963,7 +1963,7 @@
 void reiserfs_unmap_buffer(struct buffer_head *);
 
 /* file.c */
-extern struct inode_operations reiserfs_file_inode_operations;
+extern const struct inode_operations reiserfs_file_inode_operations;
 extern const struct file_operations reiserfs_file_operations;
 extern const struct address_space_operations reiserfs_address_space_operations;
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 76c8e2d..5053dc0 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -436,7 +436,7 @@
 
 	/* job control IDs */
 	pid_t pgrp;
-	pid_t tty_old_pgrp;
+	struct pid *tty_old_pgrp;
 
 	union {
 		pid_t session __deprecated;
@@ -1329,14 +1329,11 @@
 extern int kill_pid_info_as_uid(int, struct siginfo *, struct pid *, uid_t, uid_t, u32);
 extern int kill_pgrp(struct pid *pid, int sig, int priv);
 extern int kill_pid(struct pid *pid, int sig, int priv);
-extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp);
-extern int kill_pg_info(int, struct siginfo *, pid_t);
 extern void do_notify_parent(struct task_struct *, int);
 extern void force_sig(int, struct task_struct *);
 extern void force_sig_specific(int, struct task_struct *);
 extern int send_sig(int, struct task_struct *, int);
 extern void zap_other_threads(struct task_struct *p);
-extern int kill_pg(pid_t, int, int);
 extern int kill_proc(pid_t, int, int);
 extern struct sigqueue *sigqueue_alloc(void);
 extern void sigqueue_free(struct sigqueue *);
diff --git a/include/linux/security.h b/include/linux/security.h
index c554f60..7f88d97 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -2130,7 +2130,7 @@
 extern int mod_unreg_security	(const char *name, struct security_operations *ops);
 extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
 					     struct dentry *parent, void *data,
-					     struct file_operations *fops);
+					     const struct file_operations *fops);
 extern struct dentry *securityfs_create_dir(const char *name, struct dentry *parent);
 extern void securityfs_remove(struct dentry *dentry);
 
diff --git a/include/linux/spi/eeprom.h b/include/linux/spi/eeprom.h
new file mode 100644
index 0000000..1085212
--- /dev/null
+++ b/include/linux/spi/eeprom.h
@@ -0,0 +1,22 @@
+#ifndef __LINUX_SPI_EEPROM_H
+#define __LINUX_SPI_EEPROM_H
+
+/*
+ * Put one of these structures in platform_data for SPI EEPROMS handled
+ * by the "at25" driver.  On SPI, most EEPROMS understand the same core
+ * command set.  If you need to support EEPROMs that don't yet fit, add
+ * flags to support those protocol options.  These values all come from
+ * the chip datasheets.
+ */
+struct spi_eeprom {
+	u32		byte_len;
+	char		name[10];
+	u16		page_size;		/* for writes */
+	u16		flags;
+#define	EE_ADDR1	0x0001			/*  8 bit addrs */
+#define	EE_ADDR2	0x0002			/* 16 bit addrs */
+#define	EE_ADDR3	0x0004			/* 24 bit addrs */
+#define	EE_READONLY	0x0008			/* disallow writes */
+};
+
+#endif /* __LINUX_SPI_EEPROM_H */
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 176f6e3..4f0f8c2 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -114,6 +114,17 @@
 	spi->controller_state = state;
 }
 
+/* device driver data */
+
+static inline void spi_set_drvdata(struct spi_device *spi, void *data)
+{
+	dev_set_drvdata(&spi->dev, data);
+}
+
+static inline void *spi_get_drvdata(struct spi_device *spi)
+{
+	return dev_get_drvdata(&spi->dev);
+}
 
 struct spi_message;
 
@@ -137,13 +148,11 @@
 
 static inline void spi_unregister_driver(struct spi_driver *sdrv)
 {
-	if (!sdrv)
-		return;
-	driver_unregister(&sdrv->driver);
+	if (sdrv)
+		driver_unregister(&sdrv->driver);
 }
 
 
-
 /**
  * struct spi_master - interface to SPI master controller
  * @cdev: class interface to this driver
@@ -154,7 +163,8 @@
  *	each slave has a chipselect signal, but it's common that not
  *	every chipselect is connected to a slave.
  * @setup: updates the device mode and clocking records used by a
- *	device's SPI controller; protocol code may call this.
+ *	device's SPI controller; protocol code may call this.  This
+ *	must fail if an unrecognized or unsupported mode is requested.
  * @transfer: adds a message to the controller's transfer queue.
  * @cleanup: frees controller-specific state
  *
@@ -211,7 +221,7 @@
 						struct spi_message *mesg);
 
 	/* called on release() to free memory provided by spi_master */
-	void			(*cleanup)(const struct spi_device *spi);
+	void			(*cleanup)(struct spi_device *spi);
 };
 
 static inline void *spi_master_get_devdata(struct spi_master *master)
@@ -296,6 +306,16 @@
  * shifting out three bytes with word size of sixteen or twenty bits;
  * the former uses two bytes per word, the latter uses four bytes.)
  *
+ * In-memory data values are always in native CPU byte order, translated
+ * from the wire byte order (big-endian except with SPI_LSB_FIRST).  So
+ * for example when bits_per_word is sixteen, buffers are 2N bytes long
+ * and hold N sixteen bit words in CPU byte order.
+ *
+ * When the word size of the SPI transfer is not a power-of-two multiple
+ * of eight bits, those in-memory words include extra bits.  In-memory
+ * words are always seen by protocol drivers as right-justified, so the
+ * undefined (rx) or unused (tx) bits are always the most significant bits.
+ *
  * All SPI transfers start with the relevant chipselect active.  Normally
  * it stays selected until after the last transfer in a message.  Drivers
  * can affect the chipselect signal using cs_change:
@@ -453,6 +473,11 @@
  * changes those settings, and must be called from a context that can sleep.
  * The changes take effect the next time the device is selected and data
  * is transferred to or from it.
+ *
+ * Note that this call wil fail if the protocol driver specifies an option
+ * that the underlying controller or its driver does not support.  For
+ * example, not all hardware supports wire transfers using nine bit words,
+ * LSB-first wire encoding, or active-high chipselects.
  */
 static inline int
 spi_setup(struct spi_device *spi)
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index 16ce178..2e8c048 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -55,7 +55,7 @@
  * methods, if you like.
  */
 extern int spi_bitbang_setup(struct spi_device *spi);
-extern void spi_bitbang_cleanup(const struct spi_device *spi);
+extern void spi_bitbang_cleanup(struct spi_device *spi);
 extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
 extern int spi_bitbang_setup_transfer(struct spi_device *spi,
 				      struct spi_transfer *t);
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 64f3d60..83b3c7b 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -11,6 +11,7 @@
 #define SUNRPC_SVC_H
 
 #include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/auth.h>
@@ -191,7 +192,13 @@
 	iov->iov_len += sizeof(__be32);
 }
 
-	
+union svc_addr_u {
+    struct in_addr	addr;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+    struct in6_addr	addr6;
+#endif
+};
+
 /*
  * The context of a single thread, including the request currently being
  * processed.
@@ -200,8 +207,8 @@
 	struct list_head	rq_list;	/* idle list */
 	struct list_head	rq_all;		/* all threads list */
 	struct svc_sock *	rq_sock;	/* socket */
-	struct sockaddr_in	rq_addr;	/* peer address */
-	int			rq_addrlen;
+	struct sockaddr_storage	rq_addr;	/* peer address */
+	size_t			rq_addrlen;
 
 	struct svc_serv *	rq_server;	/* RPC service definition */
 	struct svc_pool *	rq_pool;	/* thread pool */
@@ -227,8 +234,8 @@
 	unsigned short
 				rq_secure  : 1;	/* secure port */
 
-
-	__be32			rq_daddr;	/* dest addr of request - reply from here */
+	union svc_addr_u	rq_daddr;	/* dest addr of request
+						 *  - reply from here */
 
 	void *			rq_argp;	/* decoded arguments */
 	void *			rq_resp;	/* xdr'd results */
@@ -256,6 +263,24 @@
 };
 
 /*
+ * Rigorous type checking on sockaddr type conversions
+ */
+static inline struct sockaddr_in *svc_addr_in(struct svc_rqst *rqst)
+{
+	return (struct sockaddr_in *) &rqst->rq_addr;
+}
+
+static inline struct sockaddr_in6 *svc_addr_in6(struct svc_rqst *rqst)
+{
+	return (struct sockaddr_in6 *) &rqst->rq_addr;
+}
+
+static inline struct sockaddr *svc_addr(struct svc_rqst *rqst)
+{
+	return (struct sockaddr *) &rqst->rq_addr;
+}
+
+/*
  * Check buffer bounds after decoding arguments
  */
 static inline int
@@ -292,9 +317,10 @@
 
 struct svc_deferred_req {
 	u32			prot;	/* protocol (UDP or TCP) */
-	struct sockaddr_in	addr;
-	struct svc_sock		*svsk;	/* where reply must go */
-	__be32			daddr;	/* where reply must come from */
+	struct svc_sock		*svsk;
+	struct sockaddr_storage	addr;	/* where reply must go */
+	size_t			addrlen;
+	union svc_addr_u	daddr;	/* where reply must come from */
 	struct cache_deferred_req handle;
 	int			argslen;
 	__be32			args[0];
@@ -368,5 +394,8 @@
 void		   svc_wake_up(struct svc_serv *);
 void		   svc_reserve(struct svc_rqst *rqstp, int space);
 struct svc_pool *  svc_pool_for_cpu(struct svc_serv *serv, int cpu);
+char *		   svc_print_addr(struct svc_rqst *, char *, size_t);
+
+#define	RPC_MAX_ADDRBUFLEN	(63U)
 
 #endif /* SUNRPC_SVC_H */
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index db312a1..cccea0a 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -57,12 +57,15 @@
 
 	/* cache of various info for TCP sockets */
 	void			*sk_info_authunix;
+
+	struct sockaddr_storage	sk_remote;	/* remote peer's address */
+	int			sk_remotelen;	/* length of address */
 };
 
 /*
  * Function prototypes.
  */
-int		svc_makesock(struct svc_serv *, int, unsigned short);
+int		svc_makesock(struct svc_serv *, int, unsigned short, int flags);
 void		svc_close_socket(struct svc_sock *);
 int		svc_recv(struct svc_rqst *, long);
 int		svc_send(struct svc_rqst *);
@@ -74,4 +77,11 @@
 			    char *name_return,
 			    int *proto);
 
+/*
+ * svc_makesock socket characteristics
+ */
+#define SVC_SOCK_DEFAULTS	(0U)
+#define SVC_SOCK_ANONYMOUS	(1U << 0)	/* don't register with pmap */
+#define SVC_SOCK_TEMPORARY	(1U << 1)	/* flag socket as temporary */
+
 #endif /* SUNRPC_SVCSOCK_H */
diff --git a/include/linux/svga.h b/include/linux/svga.h
new file mode 100644
index 0000000..eadb981
--- /dev/null
+++ b/include/linux/svga.h
@@ -0,0 +1,124 @@
+#ifndef _LINUX_SVGA_H
+#define _LINUX_SVGA_H
+
+#ifdef __KERNEL__
+
+#include <linux/pci.h>
+#include <video/vga.h>
+
+/* Terminator for register set */
+
+#define VGA_REGSET_END_VAL	0xFF
+#define VGA_REGSET_END		{VGA_REGSET_END_VAL, 0, 0}
+
+struct vga_regset {
+	u8 regnum;
+	u8 lowbit;
+	u8 highbit;
+};
+
+/* ------------------------------------------------------------------------- */
+
+#define SVGA_FORMAT_END_VAL	0xFFFF
+#define SVGA_FORMAT_END		{SVGA_FORMAT_END_VAL, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, 0, 0, 0, 0, 0, 0}
+
+struct svga_fb_format {
+	/* var part */
+	u32 bits_per_pixel;
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;
+	u32 nonstd;
+	/* fix part */
+	u32 type;
+	u32 type_aux;
+	u32 visual;
+	u32 xpanstep;
+	u32 xresstep;
+};
+
+struct svga_timing_regs {
+	const struct vga_regset *h_total_regs;
+	const struct vga_regset *h_display_regs;
+	const struct vga_regset *h_blank_start_regs;
+	const struct vga_regset *h_blank_end_regs;
+	const struct vga_regset *h_sync_start_regs;
+	const struct vga_regset *h_sync_end_regs;
+
+	const struct vga_regset *v_total_regs;
+	const struct vga_regset *v_display_regs;
+	const struct vga_regset *v_blank_start_regs;
+	const struct vga_regset *v_blank_end_regs;
+	const struct vga_regset *v_sync_start_regs;
+	const struct vga_regset *v_sync_end_regs;
+};
+
+struct svga_pll {
+	u16 m_min;
+	u16 m_max;
+	u16 n_min;
+	u16 n_max;
+	u16 r_min;
+	u16 r_max;  /* r_max < 32 */
+	u32 f_vco_min;
+	u32 f_vco_max;
+	u32 f_base;
+};
+
+
+/* Write a value to the attribute register */
+
+static inline void svga_wattr(u8 index, u8 data)
+{
+	inb(0x3DA);
+	outb(index, 0x3C0);
+	outb(data, 0x3C0);
+}
+
+/* Write a value to a sequence register with a mask */
+
+static inline void svga_wseq_mask(u8 index, u8 data, u8 mask)
+{
+	vga_wseq(NULL, index, (data & mask) | (vga_rseq(NULL, index) & ~mask));
+}
+
+/* Write a value to a CRT register with a mask */
+
+static inline void svga_wcrt_mask(u8 index, u8 data, u8 mask)
+{
+	vga_wcrt(NULL, index, (data & mask) | (vga_rcrt(NULL, index) & ~mask));
+}
+
+static inline int svga_primary_device(struct pci_dev *dev)
+{
+	u16 flags;
+	pci_read_config_word(dev, PCI_COMMAND, &flags);
+	return (flags & PCI_COMMAND_IO);
+}
+
+
+void svga_wcrt_multi(const struct vga_regset *regset, u32 value);
+void svga_wseq_multi(const struct vga_regset *regset, u32 value);
+
+void svga_set_default_gfx_regs(void);
+void svga_set_default_atc_regs(void);
+void svga_set_default_seq_regs(void);
+void svga_set_default_crt_regs(void);
+void svga_set_textmode_vga_regs(void);
+
+void svga_settile(struct fb_info *info, struct fb_tilemap *map);
+void svga_tilecopy(struct fb_info *info, struct fb_tilearea *area);
+void svga_tilefill(struct fb_info *info, struct fb_tilerect *rect);
+void svga_tileblit(struct fb_info *info, struct fb_tileblit *blit);
+void svga_tilecursor(struct fb_info *info, struct fb_tilecursor *cursor);
+
+int svga_compute_pll(const struct svga_pll *pll, u32 f_wanted, u16 *m, u16 *n, u16 *r, int node);
+int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, int node);
+void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node);
+
+int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix);
+
+#endif /* __KERNEL__  */
+#endif /* _LINUX_SVGA_H */
+
diff --git a/include/linux/toshiba.h b/include/linux/toshiba.h
index 916e5e3..6a7c4ed 100644
--- a/include/linux/toshiba.h
+++ b/include/linux/toshiba.h
@@ -33,4 +33,6 @@
 	unsigned int edi __attribute__ ((packed));
 } SMMRegisters;
 
+int tosh_smm(SMMRegisters *regs);
+
 #endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 8427c9e..dee72b9 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -197,8 +197,8 @@
 	struct mutex termios_mutex;
 	struct ktermios *termios, *termios_locked;
 	char name[64];
-	int pgrp;
-	int session;
+	struct pid *pgrp;
+	struct pid *session;
 	unsigned long flags;
 	int count;
 	struct winsize winsize;
@@ -303,7 +303,7 @@
 			     int buflen);
 extern void tty_write_message(struct tty_struct *tty, char *msg);
 
-extern int is_orphaned_pgrp(int pgrp);
+extern int is_current_pgrp_orphaned(void);
 extern int is_ignored(int sig);
 extern int tty_signal(int sig, struct tty_struct *tty);
 extern void tty_hangup(struct tty_struct * tty);
@@ -333,7 +333,6 @@
 
 extern dev_t tty_devnum(struct tty_struct *tty);
 extern void proc_clear_tty(struct task_struct *p);
-extern void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 extern void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
 extern struct tty_struct *get_current_tty(void);
 
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index d3a4f99..dc2e9fe 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -40,13 +40,16 @@
 typedef __u32 __fs32;
 typedef __u16 __fs16;
 #else
+#include <asm/div64.h>
 typedef __u64 __bitwise __fs64;
 typedef __u32 __bitwise __fs32;
 typedef __u16 __bitwise __fs16;
 #endif
 
+#ifdef __KERNEL__
 #include <linux/ufs_fs_i.h>
 #include <linux/ufs_fs_sb.h>
+#endif
 
 #define UFS_BBLOCK 0
 #define UFS_BBSIZE 8192
@@ -261,17 +264,10 @@
  */
 #define	ufs_inotocg(x)		((x) / uspi->s_ipg)
 #define	ufs_inotocgoff(x)	((x) % uspi->s_ipg)
-#define	ufs_inotofsba(x)	(ufs_cgimin(ufs_inotocg(x)) + ufs_inotocgoff(x) / uspi->s_inopf)
+#define	ufs_inotofsba(x)	(((u64)ufs_cgimin(ufs_inotocg(x))) + ufs_inotocgoff(x) / uspi->s_inopf)
 #define	ufs_inotofsbo(x)	((x) % uspi->s_inopf)
 
 /*
- * Give cylinder group number for a file system block.
- * Give cylinder group block number for a file system block.
- */
-#define	ufs_dtog(d)	((d) / uspi->s_fpg)
-#define	ufs_dtogd(d)	((d) % uspi->s_fpg)
-
-/*
  * Compute the cylinder and rotational position of a cyl block addr.
  */
 #define ufs_cbtocylno(bno) \
@@ -303,7 +299,7 @@
 #define UFS_MAXMNTLEN 512
 #define UFS2_MAXMNTLEN 468
 #define UFS2_MAXVOLLEN 32
-/* #define UFS_MAXCSBUFS 31 */
+#define UFS_MAXCSBUFS 31
 #define UFS_LINK_MAX 32000
 /*
 #define	UFS2_NOCSPTRS	((128 / sizeof(void *)) - 4)
@@ -721,6 +717,7 @@
 	__u32	c_nclusterblks;	/* number of clusters this cg */
 };	
 
+
 struct ufs_sb_private_info {
 	struct ufs_buffer_head s_ubh; /* buffer containing super block */
 	struct ufs_csum_core cs_total;
@@ -754,7 +751,7 @@
 	__u32	s_npsect;	/* # sectors/track including spares */
 	__u32	s_interleave;	/* hardware sector interleave */
 	__u32	s_trackskew;	/* sector 0 skew, per track */
-	__u32	s_csaddr;	/* blk addr of cyl grp summary area */
+	__u64	s_csaddr;	/* blk addr of cyl grp summary area */
 	__u32	s_cssize;	/* size of cyl grp summary area */
 	__u32	s_cgsize;	/* cylinder group size */
 	__u32	s_ntrak;	/* tracks per cylinder */
@@ -950,17 +947,17 @@
 #ifdef __KERNEL__
 
 /* balloc.c */
-extern void ufs_free_fragments (struct inode *, unsigned, unsigned);
-extern void ufs_free_blocks (struct inode *, unsigned, unsigned);
-extern unsigned ufs_new_fragments(struct inode *, __fs32 *, unsigned, unsigned,
-				  unsigned, int *, struct page *);
+extern void ufs_free_fragments (struct inode *, u64, unsigned);
+extern void ufs_free_blocks (struct inode *, u64, unsigned);
+extern u64 ufs_new_fragments(struct inode *, void *, u64, u64,
+			     unsigned, int *, struct page *);
 
 /* cylinder.c */
 extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);
 extern void ufs_put_cylinder (struct super_block *, unsigned);
 
 /* dir.c */
-extern struct inode_operations ufs_dir_inode_operations;
+extern const struct inode_operations ufs_dir_inode_operations;
 extern int ufs_add_link (struct dentry *, struct inode *);
 extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
 extern int ufs_make_empty(struct inode *, struct inode *);
@@ -972,7 +969,7 @@
 			 struct page *page, struct inode *inode);
 
 /* file.c */
-extern struct inode_operations ufs_file_inode_operations;
+extern const struct inode_operations ufs_file_inode_operations;
 extern const struct file_operations ufs_file_operations;
 
 extern const struct address_space_operations ufs_aops;
@@ -999,7 +996,7 @@
 extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 
 /* symlink.c */
-extern struct inode_operations ufs_fast_symlink_inode_operations;
+extern const struct inode_operations ufs_fast_symlink_inode_operations;
 
 /* truncate.c */
 extern int ufs_truncate (struct inode *, loff_t);
@@ -1014,6 +1011,22 @@
 	return container_of(inode, struct ufs_inode_info, vfs_inode);
 }
 
+/*
+ * Give cylinder group number for a file system block.
+ * Give cylinder group block number for a file system block.
+ */
+/* #define	ufs_dtog(d)	((d) / uspi->s_fpg) */
+static inline u64 ufs_dtog(struct ufs_sb_private_info * uspi, u64 b)
+{
+	do_div(b, uspi->s_fpg);
+	return b;
+}
+/* #define	ufs_dtogd(d)	((d) % uspi->s_fpg) */
+static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b)
+{
+	return do_div(b, uspi->s_fpg);
+}
+
 #endif	/* __KERNEL__ */
 
 #endif /* __LINUX_UFS_FS_H */
diff --git a/include/linux/ufs_fs_i.h b/include/linux/ufs_fs_i.h
index f50ce3b..6496caa 100644
--- a/include/linux/ufs_fs_i.h
+++ b/include/linux/ufs_fs_i.h
@@ -20,13 +20,12 @@
 		__fs64	u2_i_data[15];
 	} i_u1;
 	__u32	i_flags;
-	__u32	i_gen;
 	__u32	i_shadow;
 	__u32	i_unused1;
 	__u32	i_unused2;
 	__u32	i_oeftflag;
 	__u16	i_osync;
-	__u32	i_lastfrag;
+	__u64	i_lastfrag;
 	__u32   i_dir_start_lookup;
 	struct inode vfs_inode;
 };
diff --git a/include/linux/ufs_fs_sb.h b/include/linux/ufs_fs_sb.h
index 8ff13c1..e114c93 100644
--- a/include/linux/ufs_fs_sb.h
+++ b/include/linux/ufs_fs_sb.h
@@ -21,7 +21,6 @@
 struct ufs_sb_private_info;
 struct ufs_cg_private_info;
 struct ufs_csum;
-#define UFS_MAXCSBUFS 31
 
 struct ufs_sb_info {
 	struct ufs_sb_private_info * s_uspi;	
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 5ae10dd..47ff2f4 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -377,7 +377,7 @@
 /* ax25_route.c */
 extern void ax25_rt_device_down(struct net_device *);
 extern int  ax25_rt_ioctl(unsigned int, void __user *);
-extern struct file_operations ax25_route_fops;
+extern const struct file_operations ax25_route_fops;
 extern ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev);
 extern int  ax25_rt_autobind(ax25_cb *, ax25_address *);
 extern struct sk_buff *ax25_rt_build_path(struct sk_buff *, ax25_address *, ax25_address *, ax25_digi *);
@@ -430,7 +430,7 @@
 extern int  ax25_uid_policy;
 extern ax25_uid_assoc *ax25_findbyuid(uid_t);
 extern int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *);
-extern struct file_operations ax25_uid_fops;
+extern const struct file_operations ax25_uid_fops;
 extern void ax25_uid_free(void);
 
 /* sysctl_net_ax25.c */
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 41bcc9e..173c7c1 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -8,7 +8,7 @@
 
 extern struct list_head nf_conntrack_expect_list;
 extern struct kmem_cache *nf_conntrack_expect_cachep;
-extern struct file_operations exp_file_ops;
+extern const struct file_operations exp_file_ops;
 
 struct nf_conntrack_expect
 {
diff --git a/include/net/netrom.h b/include/net/netrom.h
index e0ca112..f06852b 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -215,8 +215,8 @@
 extern int  nr_rt_ioctl(unsigned int, void __user *);
 extern void nr_link_failed(ax25_cb *, int);
 extern int  nr_route_frame(struct sk_buff *, ax25_cb *);
-extern struct file_operations nr_nodes_fops;
-extern struct file_operations nr_neigh_fops;
+extern const struct file_operations nr_nodes_fops;
+extern const struct file_operations nr_neigh_fops;
 extern void nr_rt_free(void);
 
 /* nr_subr.c */
diff --git a/include/net/rose.h b/include/net/rose.h
index 4c05a88..a4047d3 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -189,9 +189,9 @@
 
 /* rose_route.c */
 extern struct rose_neigh rose_loopback_neigh;
-extern struct file_operations rose_neigh_fops;
-extern struct file_operations rose_nodes_fops;
-extern struct file_operations rose_routes_fops;
+extern const struct file_operations rose_neigh_fops;
+extern const struct file_operations rose_nodes_fops;
+extern const struct file_operations rose_routes_fops;
 
 extern void rose_add_loopback_neigh(void);
 extern int __must_check rose_add_loopback_node(rose_address *);
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index ee6bc2d..deff5a9 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -447,7 +447,7 @@
  *  Registering
  */
 
-extern struct file_operations snd_pcm_f_ops[2];
+extern const struct file_operations snd_pcm_f_ops[2];
 
 int snd_pcm_new(struct snd_card *card, char *id, int device,
 		int playback_count, int capture_count,
diff --git a/include/video/neomagic.h b/include/video/neomagic.h
index 78b1f15..a9e118a 100644
--- a/include/video/neomagic.h
+++ b/include/video/neomagic.h
@@ -140,7 +140,8 @@
 
 struct neofb_par {
 	struct vgastate state;
-	atomic_t ref_count;
+	struct mutex open_lock;
+	unsigned int ref_count;
 
 	unsigned char MiscOutReg;	/* Misc */
 	unsigned char CRTC[25];		/* Crtc Controller */
diff --git a/include/video/s3blit.h b/include/video/s3blit.h
deleted file mode 100644
index b1db631..0000000
--- a/include/video/s3blit.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef _VIDEO_S3BLIT_H
-#define _VIDEO_S3BLIT_H
-
-/* s3 commands */
-#define S3_BITBLT       0xc011
-#define S3_TWOPOINTLINE 0x2811
-#define S3_FILLEDRECT   0x40b1
-
-#define S3_FIFO_EMPTY 0x0400
-#define S3_HDW_BUSY   0x0200
-
-/* Enhanced register mapping (MMIO mode) */
-
-#define S3_READ_SEL      0xbee8 /* offset f */
-#define S3_MULT_MISC     0xbee8 /* offset e */
-#define S3_ERR_TERM      0x92e8
-#define S3_FRGD_COLOR    0xa6e8
-#define S3_BKGD_COLOR    0xa2e8
-#define S3_PIXEL_CNTL    0xbee8 /* offset a */
-#define S3_FRGD_MIX      0xbae8
-#define S3_BKGD_MIX      0xb6e8
-#define S3_CUR_Y         0x82e8
-#define S3_CUR_X         0x86e8
-#define S3_DESTY_AXSTP   0x8ae8
-#define S3_DESTX_DIASTP  0x8ee8
-#define S3_MIN_AXIS_PCNT 0xbee8 /* offset 0 */
-#define S3_MAJ_AXIS_PCNT 0x96e8
-#define S3_CMD           0x9ae8
-#define S3_GP_STAT       0x9ae8
-#define S3_ADVFUNC_CNTL  0x4ae8
-#define S3_WRT_MASK      0xaae8
-#define S3_RD_MASK       0xaee8
-
-/* Enhanced register mapping (Packed MMIO mode, write only) */
-#define S3_ALT_CURXY     0x8100
-#define S3_ALT_CURXY2    0x8104
-#define S3_ALT_STEP      0x8108
-#define S3_ALT_STEP2     0x810c
-#define S3_ALT_ERR       0x8110
-#define S3_ALT_CMD       0x8118
-#define S3_ALT_MIX       0x8134
-#define S3_ALT_PCNT      0x8148
-#define S3_ALT_PAT       0x8168
-
-/* Drawing modes */
-#define S3_NOTCUR          0x0000
-#define S3_LOGICALZERO     0x0001
-#define S3_LOGICALONE      0x0002
-#define S3_LEAVEASIS       0x0003
-#define S3_NOTNEW          0x0004
-#define S3_CURXORNEW       0x0005
-#define S3_NOT_CURXORNEW   0x0006
-#define S3_NEW             0x0007
-#define S3_NOTCURORNOTNEW  0x0008
-#define S3_CURORNOTNEW     0x0009
-#define S3_NOTCURORNEW     0x000a
-#define S3_CURORNEW        0x000b
-#define S3_CURANDNEW       0x000c
-#define S3_NOTCURANDNEW    0x000d
-#define S3_CURANDNOTNEW    0x000e
-#define S3_NOTCURANDNOTNEW 0x000f
-
-#define S3_CRTC_ADR    0x03d4
-#define S3_CRTC_DATA   0x03d5
-
-#define S3_REG_LOCK2 0x39
-#define S3_HGC_MODE  0x45
-
-#define S3_HWGC_ORGX_H 0x46
-#define S3_HWGC_ORGX_L 0x47
-#define S3_HWGC_ORGY_H 0x48
-#define S3_HWGC_ORGY_L 0x49
-#define S3_HWGC_DX     0x4e
-#define S3_HWGC_DY     0x4f
-
-
-#define S3_LAW_CTL 0x58
-
-#endif /* _VIDEO_S3BLIT_H */
diff --git a/init/main.c b/init/main.c
index 4e88bdd..4e9e92b 100644
--- a/init/main.c
+++ b/init/main.c
@@ -121,8 +121,12 @@
 void (*late_time_init)(void);
 extern void softirq_init(void);
 
-/* Untouched command line (eg. for /proc) saved by arch-specific code. */
-char saved_command_line[COMMAND_LINE_SIZE];
+/* Untouched command line saved by arch-specific code. */
+char __initdata boot_command_line[COMMAND_LINE_SIZE];
+/* Untouched saved command line (eg. for /proc) */
+char *saved_command_line;
+/* Command line for parameter parsing */
+static char *static_command_line;
 
 static char *execute_command;
 static char *ramdisk_execute_command;
@@ -400,6 +404,20 @@
 #endif
 
 /*
+ * We need to store the untouched command line for future reference.
+ * We also need to store the touched command line since the parameter
+ * parsing is performed in place, and we should allow a component to
+ * store reference of name/value for future reference.
+ */
+static void __init setup_command_line(char *command_line)
+{
+	saved_command_line = alloc_bootmem(strlen (boot_command_line)+1);
+	static_command_line = alloc_bootmem(strlen (command_line)+1);
+	strcpy (saved_command_line, boot_command_line);
+	strcpy (static_command_line, command_line);
+}
+
+/*
  * We need to finalize in a non-__init function or else race conditions
  * between the root thread and the init thread may cause start_kernel to
  * be reaped by free_initmem before the root thread has proceeded to
@@ -453,7 +471,7 @@
 		return;
 
 	/* All fall through to do_early_param. */
-	strlcpy(tmp_cmdline, saved_command_line, COMMAND_LINE_SIZE);
+	strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 	parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);
 	done = 1;
 }
@@ -503,6 +521,7 @@
 	printk(KERN_NOTICE);
 	printk(linux_banner);
 	setup_arch(&command_line);
+	setup_command_line(command_line);
 	unwind_setup();
 	setup_per_cpu_areas();
 	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */
@@ -520,9 +539,9 @@
 	preempt_disable();
 	build_all_zonelists();
 	page_alloc_init();
-	printk(KERN_NOTICE "Kernel command line: %s\n", saved_command_line);
+	printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
 	parse_early_param();
-	parse_args("Booting kernel", command_line, __start___param,
+	parse_args("Booting kernel", static_command_line, __start___param,
 		   __stop___param - __start___param,
 		   &unknown_bootoption);
 	if (!irqs_disabled()) {
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 02717f7..7a8ce610 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -84,8 +84,8 @@
 	unsigned long qsize; /* size of queue in memory (sum of all msgs) */
 };
 
-static struct inode_operations mqueue_dir_inode_operations;
-static struct file_operations mqueue_file_operations;
+static const struct inode_operations mqueue_dir_inode_operations;
+static const struct file_operations mqueue_file_operations;
 static struct super_operations mqueue_super_ops;
 static void remove_notification(struct mqueue_inode_info *info);
 
@@ -1160,13 +1160,13 @@
 	return ret;
 }
 
-static struct inode_operations mqueue_dir_inode_operations = {
+static const struct inode_operations mqueue_dir_inode_operations = {
 	.lookup = simple_lookup,
 	.create = mqueue_create,
 	.unlink = mqueue_unlink,
 };
 
-static struct file_operations mqueue_file_operations = {
+static const struct file_operations mqueue_file_operations = {
 	.flush = mqueue_flush_file,
 	.poll = mqueue_poll_file,
 	.read = mqueue_read_file,
diff --git a/ipc/shm.c b/ipc/shm.c
index f8e10a2..5bb617f 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -42,7 +42,7 @@
 
 #include "util.h"
 
-static struct file_operations shm_file_operations;
+static const struct file_operations shm_file_operations;
 static struct vm_operations_struct shm_vm_ops;
 
 static struct ipc_ids init_shm_ids;
@@ -249,7 +249,7 @@
 	return 0;
 }
 
-static struct file_operations shm_file_operations = {
+static const struct file_operations shm_file_operations = {
 	.mmap		= shm_mmap,
 	.release	= shm_release,
 #ifndef CONFIG_MMU
diff --git a/ipc/util.c b/ipc/util.c
index 0c97cb7..08a6479 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -205,7 +205,7 @@
 }
 
 #ifdef CONFIG_PROC_FS
-static struct file_operations sysvipc_proc_fops;
+static const struct file_operations sysvipc_proc_fops;
 /**
  *	ipc_init_proc_interface	-  Create a proc interface for sysipc types using a seq_file interface.
  *	@path: Path in procfs
@@ -738,14 +738,20 @@
 #endif /* __ARCH_WANT_IPC_PARSE_VERSION */
 
 #ifdef CONFIG_PROC_FS
+struct ipc_proc_iter {
+	struct ipc_namespace *ns;
+	struct ipc_proc_iface *iface;
+};
+
 static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
 {
-	struct ipc_proc_iface *iface = s->private;
+	struct ipc_proc_iter *iter = s->private;
+	struct ipc_proc_iface *iface = iter->iface;
 	struct kern_ipc_perm *ipc = it;
 	loff_t p;
 	struct ipc_ids *ids;
 
-	ids = current->nsproxy->ipc_ns->ids[iface->ids];
+	ids = iter->ns->ids[iface->ids];
 
 	/* If we had an ipc id locked before, unlock it */
 	if (ipc && ipc != SEQ_START_TOKEN)
@@ -772,12 +778,13 @@
  */
 static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
 {
-	struct ipc_proc_iface *iface = s->private;
+	struct ipc_proc_iter *iter = s->private;
+	struct ipc_proc_iface *iface = iter->iface;
 	struct kern_ipc_perm *ipc;
 	loff_t p;
 	struct ipc_ids *ids;
 
-	ids = current->nsproxy->ipc_ns->ids[iface->ids];
+	ids = iter->ns->ids[iface->ids];
 
 	/*
 	 * Take the lock - this will be released by the corresponding
@@ -806,21 +813,23 @@
 static void sysvipc_proc_stop(struct seq_file *s, void *it)
 {
 	struct kern_ipc_perm *ipc = it;
-	struct ipc_proc_iface *iface = s->private;
+	struct ipc_proc_iter *iter = s->private;
+	struct ipc_proc_iface *iface = iter->iface;
 	struct ipc_ids *ids;
 
 	/* If we had a locked segment, release it */
 	if (ipc && ipc != SEQ_START_TOKEN)
 		ipc_unlock(ipc);
 
-	ids = current->nsproxy->ipc_ns->ids[iface->ids];
+	ids = iter->ns->ids[iface->ids];
 	/* Release the lock we took in start() */
 	mutex_unlock(&ids->mutex);
 }
 
 static int sysvipc_proc_show(struct seq_file *s, void *it)
 {
-	struct ipc_proc_iface *iface = s->private;
+	struct ipc_proc_iter *iter = s->private;
+	struct ipc_proc_iface *iface = iter->iface;
 
 	if (it == SEQ_START_TOKEN)
 		return seq_puts(s, iface->header);
@@ -835,22 +844,45 @@
 	.show  = sysvipc_proc_show,
 };
 
-static int sysvipc_proc_open(struct inode *inode, struct file *file) {
+static int sysvipc_proc_open(struct inode *inode, struct file *file)
+{
 	int ret;
 	struct seq_file *seq;
+	struct ipc_proc_iter *iter;
+
+	ret = -ENOMEM;
+	iter = kmalloc(sizeof(*iter), GFP_KERNEL);
+	if (!iter)
+		goto out;
 
 	ret = seq_open(file, &sysvipc_proc_seqops);
-	if (!ret) {
-		seq = file->private_data;
-		seq->private = PDE(inode)->data;
-	}
+	if (ret)
+		goto out_kfree;
+
+	seq = file->private_data;
+	seq->private = iter;
+
+	iter->iface = PDE(inode)->data;
+	iter->ns    = get_ipc_ns(current->nsproxy->ipc_ns);
+out:
 	return ret;
+out_kfree:
+	kfree(iter);
+	goto out;
 }
 
-static struct file_operations sysvipc_proc_fops = {
+static int sysvipc_proc_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq = file->private_data;
+	struct ipc_proc_iter *iter = seq->private;
+	put_ipc_ns(iter->ns);
+	return seq_release_private(inode, file);
+}
+
+static const struct file_operations sysvipc_proc_fops = {
 	.open    = sysvipc_proc_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release,
+	.release = sysvipc_proc_release,
 };
 #endif /* CONFIG_PROC_FS */
diff --git a/kernel/capability.c b/kernel/capability.c
index edb845a..c8d3c77 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -92,15 +92,17 @@
  * cap_set_pg - set capabilities for all processes in a given process
  * group.  We call this holding task_capability_lock and tasklist_lock.
  */
-static inline int cap_set_pg(int pgrp, kernel_cap_t *effective,
+static inline int cap_set_pg(int pgrp_nr, kernel_cap_t *effective,
 			      kernel_cap_t *inheritable,
 			      kernel_cap_t *permitted)
 {
 	struct task_struct *g, *target;
 	int ret = -EPERM;
 	int found = 0;
+	struct pid *pgrp;
 
-	do_each_task_pid(pgrp, PIDTYPE_PGID, g) {
+	pgrp = find_pid(pgrp_nr);
+	do_each_pid_task(pgrp, PIDTYPE_PGID, g) {
 		target = g;
 		while_each_thread(g, target) {
 			if (!security_capset_check(target, effective,
@@ -113,7 +115,7 @@
 			}
 			found = 1;
 		}
-	} while_each_task_pid(pgrp, PIDTYPE_PGID, g);
+	} while_each_pid_task(pgrp, PIDTYPE_PGID, g);
 
 	if (!found)
 	     ret = 0;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 6b05dc6..f382b0f 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1540,7 +1540,7 @@
 	.release = cpuset_file_release,
 };
 
-static struct inode_operations cpuset_dir_inode_operations = {
+static const struct inode_operations cpuset_dir_inode_operations = {
 	.lookup = simple_lookup,
 	.mkdir = cpuset_mkdir,
 	.rmdir = cpuset_rmdir,
@@ -2656,7 +2656,7 @@
 	return single_open(file, proc_cpuset_show, pid);
 }
 
-struct file_operations proc_cpuset_operations = {
+const struct file_operations proc_cpuset_operations = {
 	.open		= cpuset_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/kernel/exit.c b/kernel/exit.c
index bc71fdf..f132349 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -185,21 +185,19 @@
  * This checks not only the pgrp, but falls back on the pid if no
  * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
  * without this...
+ *
+ * The caller must hold rcu lock or the tasklist lock.
  */
-int session_of_pgrp(int pgrp)
+struct pid *session_of_pgrp(struct pid *pgrp)
 {
 	struct task_struct *p;
-	int sid = 0;
+	struct pid *sid = NULL;
 
-	read_lock(&tasklist_lock);
-
-	p = find_task_by_pid_type(PIDTYPE_PGID, pgrp);
+	p = pid_task(pgrp, PIDTYPE_PGID);
 	if (p == NULL)
-		p = find_task_by_pid(pgrp);
+		p = pid_task(pgrp, PIDTYPE_PID);
 	if (p != NULL)
-		sid = process_session(p);
-
-	read_unlock(&tasklist_lock);
+		sid = task_session(p);
 
 	return sid;
 }
@@ -212,47 +210,47 @@
  *
  * "I ask you, have you ever known what it is to be an orphan?"
  */
-static int will_become_orphaned_pgrp(int pgrp, struct task_struct *ignored_task)
+static int will_become_orphaned_pgrp(struct pid *pgrp, struct task_struct *ignored_task)
 {
 	struct task_struct *p;
 	int ret = 1;
 
-	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
+	do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 		if (p == ignored_task
 				|| p->exit_state
 				|| is_init(p->real_parent))
 			continue;
-		if (process_group(p->real_parent) != pgrp &&
-		    process_session(p->real_parent) == process_session(p)) {
+		if (task_pgrp(p->real_parent) != pgrp &&
+		    task_session(p->real_parent) == task_session(p)) {
 			ret = 0;
 			break;
 		}
-	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
+	} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 	return ret;	/* (sighing) "Often!" */
 }
 
-int is_orphaned_pgrp(int pgrp)
+int is_current_pgrp_orphaned(void)
 {
 	int retval;
 
 	read_lock(&tasklist_lock);
-	retval = will_become_orphaned_pgrp(pgrp, NULL);
+	retval = will_become_orphaned_pgrp(task_pgrp(current), NULL);
 	read_unlock(&tasklist_lock);
 
 	return retval;
 }
 
-static int has_stopped_jobs(int pgrp)
+static int has_stopped_jobs(struct pid *pgrp)
 {
 	int retval = 0;
 	struct task_struct *p;
 
-	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
+	do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 		if (p->state != TASK_STOPPED)
 			continue;
 		retval = 1;
 		break;
-	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
+	} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 	return retval;
 }
 
@@ -430,8 +428,10 @@
 		while (set) {
 			if (set & 1) {
 				struct file * file = xchg(&fdt->fd[i], NULL);
-				if (file)
+				if (file) {
 					filp_close(file, files);
+					cond_resched();
+				}
 			}
 			i++;
 			set >>= 1;
@@ -648,14 +648,14 @@
 	 * than we are, and it was the only connection
 	 * outside, so the child pgrp is now orphaned.
 	 */
-	if ((process_group(p) != process_group(father)) &&
-	    (process_session(p) == process_session(father))) {
-		int pgrp = process_group(p);
+	if ((task_pgrp(p) != task_pgrp(father)) &&
+	    (task_session(p) == task_session(father))) {
+		struct pid *pgrp = task_pgrp(p);
 
 		if (will_become_orphaned_pgrp(pgrp, NULL) &&
 		    has_stopped_jobs(pgrp)) {
-			__kill_pg_info(SIGHUP, SEND_SIG_PRIV, pgrp);
-			__kill_pg_info(SIGCONT, SEND_SIG_PRIV, pgrp);
+			__kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
+			__kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
 		}
 	}
 }
@@ -735,6 +735,7 @@
 	int state;
 	struct task_struct *t;
 	struct list_head ptrace_dead, *_p, *_n;
+	struct pid *pgrp;
 
 	if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
 	    && !thread_group_empty(tsk)) {
@@ -787,12 +788,13 @@
 	 
 	t = tsk->real_parent;
 	
-	if ((process_group(t) != process_group(tsk)) &&
-	    (process_session(t) == process_session(tsk)) &&
-	    will_become_orphaned_pgrp(process_group(tsk), tsk) &&
-	    has_stopped_jobs(process_group(tsk))) {
-		__kill_pg_info(SIGHUP, SEND_SIG_PRIV, process_group(tsk));
-		__kill_pg_info(SIGCONT, SEND_SIG_PRIV, process_group(tsk));
+	pgrp = task_pgrp(tsk);
+	if ((task_pgrp(t) != pgrp) &&
+	    (task_session(t) != task_session(tsk)) &&
+	    will_become_orphaned_pgrp(pgrp, tsk) &&
+	    has_stopped_jobs(pgrp)) {
+		__kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);
+		__kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);
 	}
 
 	/* Let father know we died 
diff --git a/kernel/fork.c b/kernel/fork.c
index 80284eb..0b6293d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -869,7 +869,7 @@
 	sig->it_prof_incr = cputime_zero;
 
 	sig->leader = 0;	/* session leadership doesn't inherit */
-	sig->tty_old_pgrp = 0;
+	sig->tty_old_pgrp = NULL;
 
 	sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
 	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 8b961ad..7c85d69 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -328,12 +328,14 @@
 	return 0;
 
 mismatch:
+#ifdef CONFIG_DEBUG_SHIRQ
 	if (!(new->flags & IRQF_PROBE_SHARED)) {
 		printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq);
 		if (old_name)
 			printk(KERN_ERR "current handler: %s\n", old_name);
 		dump_stack();
 	}
+#endif
 	spin_unlock_irqrestore(&desc->lock, flags);
 	return -EBUSY;
 }
@@ -357,6 +359,7 @@
 	struct irq_desc *desc;
 	struct irqaction **p;
 	unsigned long flags;
+	irqreturn_t (*handler)(int, void *) = NULL;
 
 	WARN_ON(in_interrupt());
 	if (irq >= NR_IRQS)
@@ -396,6 +399,8 @@
 
 			/* Make sure it's not being used on another CPU */
 			synchronize_irq(irq);
+			if (action->flags & IRQF_SHARED)
+				handler = action->handler;
 			kfree(action);
 			return;
 		}
@@ -403,6 +408,17 @@
 		spin_unlock_irqrestore(&desc->lock, flags);
 		return;
 	}
+#ifdef CONFIG_DEBUG_SHIRQ
+	if (handler) {
+		/*
+		 * It's a shared IRQ -- the driver ought to be prepared for it
+		 * to happen even now it's being freed, so let's make sure....
+		 * We do this after actually deregistering it, to make sure that
+		 * a 'real' IRQ doesn't run in parallel with our fake
+		 */
+		handler(irq, dev_id);
+	}
+#endif
 }
 EXPORT_SYMBOL(free_irq);
 
@@ -475,6 +491,25 @@
 
 	select_smp_affinity(irq);
 
+#ifdef CONFIG_DEBUG_SHIRQ
+	if (irqflags & IRQF_SHARED) {
+		/*
+		 * It's a shared IRQ -- the driver ought to be prepared for it
+		 * to happen immediately, so let's make sure....
+		 * We do this before actually registering it, to make sure that
+		 * a 'real' IRQ doesn't run in parallel with our fake
+		 */
+		if (irqflags & IRQF_DISABLED) {
+			unsigned long flags;
+
+			local_irq_save(flags);
+			handler(irq, dev_id);
+			local_irq_restore(flags);
+		} else
+			handler(irq, dev_id);
+	}
+#endif
+
 	retval = setup_irq(irq, action);
 	if (retval)
 		kfree(action);
diff --git a/kernel/sched.c b/kernel/sched.c
index 1fd67e1..08f8617 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -2897,14 +2897,16 @@
 static void update_load(struct rq *this_rq)
 {
 	unsigned long this_load;
-	int i, scale;
+	unsigned int i, scale;
 
 	this_load = this_rq->raw_weighted_load;
 
 	/* Update our load: */
-	for (i = 0, scale = 1; i < 3; i++, scale <<= 1) {
+	for (i = 0, scale = 1; i < 3; i++, scale += scale) {
 		unsigned long old_load, new_load;
 
+		/* scale is effectively 1 << i now, and >> i divides by scale */
+
 		old_load = this_rq->cpu_load[i];
 		new_load = this_load;
 		/*
@@ -2914,7 +2916,7 @@
 		 */
 		if (new_load > old_load)
 			new_load += scale-1;
-		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) / scale;
+		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
 	}
 }
 
diff --git a/kernel/signal.c b/kernel/signal.c
index 228fdb5..8072e56 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1096,26 +1096,6 @@
 	return retval;
 }
 
-int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
-{
-	if (pgrp <= 0)
-		return -EINVAL;
-
-	return __kill_pgrp_info(sig, info, find_pid(pgrp));
-}
-
-int
-kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
-{
-	int retval;
-
-	read_lock(&tasklist_lock);
-	retval = __kill_pg_info(sig, info, pgrp);
-	read_unlock(&tasklist_lock);
-
-	return retval;
-}
-
 int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
 {
 	int error;
@@ -1191,8 +1171,10 @@
 
 static int kill_something_info(int sig, struct siginfo *info, int pid)
 {
+	int ret;
+	rcu_read_lock();
 	if (!pid) {
-		return kill_pg_info(sig, info, process_group(current));
+		ret = kill_pgrp_info(sig, info, task_pgrp(current));
 	} else if (pid == -1) {
 		int retval = 0, count = 0;
 		struct task_struct * p;
@@ -1207,12 +1189,14 @@
 			}
 		}
 		read_unlock(&tasklist_lock);
-		return count ? retval : -ESRCH;
+		ret = count ? retval : -ESRCH;
 	} else if (pid < 0) {
-		return kill_pg_info(sig, info, -pid);
+		ret = kill_pgrp_info(sig, info, find_pid(-pid));
 	} else {
-		return kill_proc_info(sig, info, pid);
+		ret = kill_pid_info(sig, info, find_pid(pid));
 	}
+	rcu_read_unlock();
+	return ret;
 }
 
 /*
@@ -1311,12 +1295,6 @@
 EXPORT_SYMBOL(kill_pid);
 
 int
-kill_pg(pid_t pgrp, int sig, int priv)
-{
-	return kill_pg_info(sig, __si_special(priv), pgrp);
-}
-
-int
 kill_proc(pid_t pid, int sig, int priv)
 {
 	return kill_proc_info(sig, __si_special(priv), pid);
@@ -1905,7 +1883,7 @@
 
 				/* signals can be posted during this window */
 
-				if (is_orphaned_pgrp(process_group(current)))
+				if (is_current_pgrp_orphaned())
 					goto relock;
 
 				spin_lock_irq(&current->sighand->siglock);
@@ -1955,7 +1933,6 @@
 EXPORT_SYMBOL_GPL(dequeue_signal);
 EXPORT_SYMBOL(flush_signals);
 EXPORT_SYMBOL(force_sig);
-EXPORT_SYMBOL(kill_pg);
 EXPORT_SYMBOL(kill_proc);
 EXPORT_SYMBOL(ptrace_notify);
 EXPORT_SYMBOL(send_sig);
diff --git a/kernel/sys.c b/kernel/sys.c
index e102438..123b165 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -596,6 +596,7 @@
 	struct task_struct *g, *p;
 	struct user_struct *user;
 	int error = -EINVAL;
+	struct pid *pgrp;
 
 	if (which > 2 || which < 0)
 		goto out;
@@ -610,18 +611,21 @@
 	read_lock(&tasklist_lock);
 	switch (which) {
 		case PRIO_PROCESS:
-			if (!who)
-				who = current->pid;
-			p = find_task_by_pid(who);
+			if (who)
+				p = find_task_by_pid(who);
+			else
+				p = current;
 			if (p)
 				error = set_one_prio(p, niceval, error);
 			break;
 		case PRIO_PGRP:
-			if (!who)
-				who = process_group(current);
-			do_each_task_pid(who, PIDTYPE_PGID, p) {
+			if (who)
+				pgrp = find_pid(who);
+			else
+				pgrp = task_pgrp(current);
+			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 				error = set_one_prio(p, niceval, error);
-			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
 			user = current->user;
@@ -656,6 +660,7 @@
 	struct task_struct *g, *p;
 	struct user_struct *user;
 	long niceval, retval = -ESRCH;
+	struct pid *pgrp;
 
 	if (which > 2 || which < 0)
 		return -EINVAL;
@@ -663,9 +668,10 @@
 	read_lock(&tasklist_lock);
 	switch (which) {
 		case PRIO_PROCESS:
-			if (!who)
-				who = current->pid;
-			p = find_task_by_pid(who);
+			if (who)
+				p = find_task_by_pid(who);
+			else
+				p = current;
 			if (p) {
 				niceval = 20 - task_nice(p);
 				if (niceval > retval)
@@ -673,13 +679,15 @@
 			}
 			break;
 		case PRIO_PGRP:
-			if (!who)
-				who = process_group(current);
-			do_each_task_pid(who, PIDTYPE_PGID, p) {
+			if (who)
+				pgrp = find_pid(who);
+			else
+				pgrp = task_pgrp(current);
+			do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
 				niceval = 20 - task_nice(p);
 				if (niceval > retval)
 					retval = niceval;
-			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			} while_each_pid_task(pgrp, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
 			user = current->user;
@@ -1388,7 +1396,7 @@
 
 	if (p->real_parent == group_leader) {
 		err = -EPERM;
-		if (process_session(p) != process_session(group_leader))
+		if (task_session(p) != task_session(group_leader))
 			goto out;
 		err = -EACCES;
 		if (p->did_exec)
@@ -1407,7 +1415,7 @@
 		struct task_struct *g =
 			find_task_by_pid_type(PIDTYPE_PGID, pgid);
 
-		if (!g || process_session(g) != process_session(group_leader))
+		if (!g || task_session(g) != task_session(group_leader))
 			goto out;
 	}
 
@@ -1510,7 +1518,6 @@
 
 	spin_lock(&group_leader->sighand->siglock);
 	group_leader->signal->tty = NULL;
-	group_leader->signal->tty_old_pgrp = 0;
 	spin_unlock(&group_leader->sighand->siglock);
 
 	err = process_group(group_leader);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 356a5ab..63f04c1 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -77,6 +77,15 @@
 	  Say Y here if you are developing drivers or trying to debug and
 	  identify kernel problems.
 
+config DEBUG_SHIRQ
+	bool "Debug shared IRQ handlers"
+	depends on DEBUG_KERNEL && GENERIC_HARDIRQS
+	help
+	  Enable this to generate a spurious interrupt as soon as a shared
+	  interrupt handler is registered, and just before one is deregistered.
+	  Drivers ought to be able to handle interrupts coming in at those
+	  points; some don't and need to be caught.
+
 config LOG_BUF_SHIFT
 	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
 	range 12 21
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 50a4380..623a68a 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -313,7 +313,7 @@
 #endif
 
 #ifndef SWIOTLB_ARCH_HAS_NEEDS_MAPPING
-static inline int
+static int
 address_needs_mapping(struct device *hwdev, dma_addr_t addr)
 {
 	dma_addr_t mask = 0xffffffff;
@@ -672,7 +672,7 @@
  * address back to the card, you must first perform a
  * swiotlb_dma_sync_for_device, and then the device again owns the buffer
  */
-static inline void
+static void
 swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
 		    size_t size, int dir, int target)
 {
@@ -702,7 +702,7 @@
 /*
  * Same as above, but for a sub-range of the mapping.
  */
-static inline void
+static void
 swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr,
 			  unsigned long offset, size_t size,
 			  int dir, int target)
@@ -805,7 +805,7 @@
  * The same as swiotlb_sync_single_* but for a scatter-gather list, same rules
  * and usage.
  */
-static inline void
+static void
 swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg,
 		int nelems, int dir, int target)
 {
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 44f0e33..b025864 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -554,8 +554,7 @@
  * @...: Arguments for the format string
  *
  * The return value is the number of characters written into @buf not including
- * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
- * greater than or equal to @size, the resulting string is truncated.
+ * the trailing '\0'. If @size is <= 0 the function returns 0.
  */
 
 int scnprintf(char * buf, size_t size, const char *fmt, ...)
diff --git a/mm/memory.c b/mm/memory.c
index 072c113..e7066e7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1277,6 +1277,51 @@
 }
 EXPORT_SYMBOL(vm_insert_page);
 
+/**
+ * vm_insert_pfn - insert single pfn into user vma
+ * @vma: user vma to map to
+ * @addr: target user address of this page
+ * @pfn: source kernel pfn
+ *
+ * Similar to vm_inert_page, this allows drivers to insert individual pages
+ * they've allocated into a user vma. Same comments apply.
+ *
+ * This function should only be called from a vm_ops->fault handler, and
+ * in that case the handler should return NULL.
+ */
+int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
+		unsigned long pfn)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	int retval;
+	pte_t *pte, entry;
+	spinlock_t *ptl;
+
+	BUG_ON(!(vma->vm_flags & VM_PFNMAP));
+	BUG_ON(is_cow_mapping(vma->vm_flags));
+
+	retval = -ENOMEM;
+	pte = get_locked_pte(mm, addr, &ptl);
+	if (!pte)
+		goto out;
+	retval = -EBUSY;
+	if (!pte_none(*pte))
+		goto out_unlock;
+
+	/* Ok, finally just insert the thing.. */
+	entry = pfn_pte(pfn, vma->vm_page_prot);
+	set_pte_at(mm, addr, pte, entry);
+	update_mmu_cache(vma, addr, entry);
+
+	retval = 0;
+out_unlock:
+	pte_unmap_unlock(pte, ptl);
+
+out:
+	return retval;
+}
+EXPORT_SYMBOL(vm_insert_pfn);
+
 /*
  * maps a range of physical memory into the requested pages. the old
  * mappings are removed. any references to nonexistent pages results
@@ -2310,10 +2355,12 @@
 	BUG_ON(is_cow_mapping(vma->vm_flags));
 
 	pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK);
-	if (pfn == NOPFN_OOM)
+	if (unlikely(pfn == NOPFN_OOM))
 		return VM_FAULT_OOM;
-	if (pfn == NOPFN_SIGBUS)
+	else if (unlikely(pfn == NOPFN_SIGBUS))
 		return VM_FAULT_SIGBUS;
+	else if (unlikely(pfn == NOPFN_REFAULT))
+		return VM_FAULT_MINOR;
 
 	page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
 
diff --git a/mm/mincore.c b/mm/mincore.c
index 8aca6f7..95c5f49 100644
--- a/mm/mincore.c
+++ b/mm/mincore.c
@@ -12,6 +12,8 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/syscalls.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -22,14 +24,22 @@
  * and is up to date; i.e. that no page-in operation would be required
  * at this time if an application were to map and access this page.
  */
-static unsigned char mincore_page(struct vm_area_struct * vma,
-	unsigned long pgoff)
+static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
 {
 	unsigned char present = 0;
-	struct address_space * as = vma->vm_file->f_mapping;
-	struct page * page;
+	struct page *page;
 
-	page = find_get_page(as, pgoff);
+	/*
+	 * When tmpfs swaps out a page from a file, any process mapping that
+	 * file will not get a swp_entry_t in its pte, but rather it is like
+	 * any other file mapping (ie. marked !present and faulted in with
+	 * tmpfs's .nopage). So swapped out tmpfs mappings are tested here.
+	 *
+	 * However when tmpfs moves the page from pagecache and into swapcache,
+	 * it is still in core, but the find_get_page below won't find it.
+	 * No big deal, but make a note of it.
+	 */
+	page = find_get_page(mapping, pgoff);
 	if (page) {
 		present = PageUptodate(page);
 		page_cache_release(page);
@@ -45,7 +55,14 @@
  */
 static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pages)
 {
-	unsigned long i, nr, pgoff;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *ptep;
+	spinlock_t *ptl;
+	unsigned long nr;
+	int i;
+	pgoff_t pgoff;
 	struct vm_area_struct *vma = find_vma(current->mm, addr);
 
 	/*
@@ -56,31 +73,64 @@
 		return -ENOMEM;
 
 	/*
-	 * Ok, got it. But check whether it's a segment we support
-	 * mincore() on. Right now, we don't do any anonymous mappings.
-	 *
-	 * FIXME: This is just stupid. And returning ENOMEM is 
-	 * stupid too. We should just look at the page tables. But
-	 * this is what we've traditionally done, so we'll just
-	 * continue doing it.
+	 * Calculate how many pages there are left in the last level of the
+	 * PTE array for our address.
 	 */
-	if (!vma->vm_file)
-		return -ENOMEM;
-
-	/*
-	 * Calculate how many pages there are left in the vma, and
-	 * what the pgoff is for our address.
-	 */
-	nr = (vma->vm_end - addr) >> PAGE_SHIFT;
+	nr = PTRS_PER_PTE - ((addr >> PAGE_SHIFT) & (PTRS_PER_PTE-1));
 	if (nr > pages)
 		nr = pages;
 
-	pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
-	pgoff += vma->vm_pgoff;
+	pgd = pgd_offset(vma->vm_mm, addr);
+	if (pgd_none_or_clear_bad(pgd))
+		goto none_mapped;
+	pud = pud_offset(pgd, addr);
+	if (pud_none_or_clear_bad(pud))
+		goto none_mapped;
+	pmd = pmd_offset(pud, addr);
+	if (pmd_none_or_clear_bad(pmd))
+		goto none_mapped;
 
-	/* And then we just fill the sucker in.. */
-	for (i = 0 ; i < nr; i++, pgoff++)
-		vec[i] = mincore_page(vma, pgoff);
+	ptep = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+	for (i = 0; i < nr; i++, ptep++, addr += PAGE_SIZE) {
+		unsigned char present;
+		pte_t pte = *ptep;
+
+		if (pte_present(pte)) {
+			present = 1;
+
+		} else if (pte_none(pte)) {
+			if (vma->vm_file) {
+				pgoff = linear_page_index(vma, addr);
+				present = mincore_page(vma->vm_file->f_mapping,
+							pgoff);
+			} else
+				present = 0;
+
+		} else if (pte_file(pte)) {
+			pgoff = pte_to_pgoff(pte);
+			present = mincore_page(vma->vm_file->f_mapping, pgoff);
+
+		} else { /* pte is a swap entry */
+			swp_entry_t entry = pte_to_swp_entry(pte);
+			if (is_migration_entry(entry)) {
+				/* migration entries are always uptodate */
+				present = 1;
+			} else {
+				pgoff = entry.val;
+				present = mincore_page(&swapper_space, pgoff);
+			}
+		}
+	}
+	pte_unmap_unlock(ptep-1, ptl);
+
+	return nr;
+
+none_mapped:
+	if (vma->vm_file) {
+		pgoff = linear_page_index(vma, addr);
+		for (i = 0; i < nr; i++, pgoff++)
+			vec[i] = mincore_page(vma->vm_file->f_mapping, pgoff);
+	}
 
 	return nr;
 }
diff --git a/mm/shmem.c b/mm/shmem.c
index b38e171..8820530 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -178,9 +178,9 @@
 static struct super_operations shmem_ops;
 static const struct address_space_operations shmem_aops;
 static const struct file_operations shmem_file_operations;
-static struct inode_operations shmem_inode_operations;
-static struct inode_operations shmem_dir_inode_operations;
-static struct inode_operations shmem_special_inode_operations;
+static const struct inode_operations shmem_inode_operations;
+static const struct inode_operations shmem_dir_inode_operations;
+static const struct inode_operations shmem_special_inode_operations;
 static struct vm_operations_struct shmem_vm_ops;
 
 static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
@@ -1410,8 +1410,8 @@
 }
 
 #ifdef CONFIG_TMPFS
-static struct inode_operations shmem_symlink_inode_operations;
-static struct inode_operations shmem_symlink_inline_operations;
+static const struct inode_operations shmem_symlink_inode_operations;
+static const struct inode_operations shmem_symlink_inline_operations;
 
 /*
  * Normally tmpfs makes no use of shmem_prepare_write, but it
@@ -1904,12 +1904,12 @@
 	}
 }
 
-static struct inode_operations shmem_symlink_inline_operations = {
+static const struct inode_operations shmem_symlink_inline_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= shmem_follow_link_inline,
 };
 
-static struct inode_operations shmem_symlink_inode_operations = {
+static const struct inode_operations shmem_symlink_inode_operations = {
 	.truncate	= shmem_truncate,
 	.readlink	= generic_readlink,
 	.follow_link	= shmem_follow_link,
@@ -2335,7 +2335,7 @@
 #endif
 };
 
-static struct inode_operations shmem_inode_operations = {
+static const struct inode_operations shmem_inode_operations = {
 	.truncate	= shmem_truncate,
 	.setattr	= shmem_notify_change,
 	.truncate_range	= shmem_truncate_range,
@@ -2349,7 +2349,7 @@
 
 };
 
-static struct inode_operations shmem_dir_inode_operations = {
+static const struct inode_operations shmem_dir_inode_operations = {
 #ifdef CONFIG_TMPFS
 	.create		= shmem_create,
 	.lookup		= simple_lookup,
@@ -2371,7 +2371,7 @@
 #endif
 };
 
-static struct inode_operations shmem_special_inode_operations = {
+static const struct inode_operations shmem_special_inode_operations = {
 #ifdef CONFIG_TMPFS_POSIX_ACL
 	.setattr	= shmem_notify_change,
 	.setxattr	= generic_setxattr,
diff --git a/net/802/tr.c b/net/802/tr.c
index 31509f6..96bd144 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -576,7 +576,7 @@
 	return seq_open(file, &rif_seq_ops);
 }
 
-static struct file_operations rif_seq_fops = {
+static const struct file_operations rif_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = rif_seq_open,
 	.read    = seq_read,
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index 1b72c98..5e24f72 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -81,7 +81,7 @@
 	return seq_open(file, &vlan_seq_ops);
 }
 
-static struct file_operations vlan_fops = {
+static const struct file_operations vlan_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = vlan_seq_open,
 	.read    = seq_read,
@@ -98,7 +98,7 @@
 	return single_open(file, vlandev_seq_show, PDE(inode)->data);
 }
 
-static struct file_operations vlandev_fops = {
+static const struct file_operations vlandev_fops = {
 	.owner = THIS_MODULE,
 	.open    = vlandev_seq_open,
 	.read    = seq_read,
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 27e845d..d89d62f 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -1048,7 +1048,7 @@
 	goto out;
 }
 
-struct file_operations atalk_seq_arp_fops = {
+const struct file_operations atalk_seq_arp_fops = {
 	.owner		= THIS_MODULE,
 	.open           = aarp_seq_open,
 	.read           = seq_read,
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
index bc3015f..57ff812 100644
--- a/net/appletalk/atalk_proc.c
+++ b/net/appletalk/atalk_proc.c
@@ -240,7 +240,7 @@
 	return seq_open(file, &atalk_seq_socket_ops);
 }
 
-static struct file_operations atalk_seq_interface_fops = {
+static const struct file_operations atalk_seq_interface_fops = {
 	.owner		= THIS_MODULE,
 	.open		= atalk_seq_interface_open,
 	.read		= seq_read,
@@ -248,7 +248,7 @@
 	.release	= seq_release,
 };
 
-static struct file_operations atalk_seq_route_fops = {
+static const struct file_operations atalk_seq_route_fops = {
 	.owner		= THIS_MODULE,
 	.open		= atalk_seq_route_open,
 	.read		= seq_read,
@@ -256,7 +256,7 @@
 	.release	= seq_release,
 };
 
-static struct file_operations atalk_seq_socket_fops = {
+static const struct file_operations atalk_seq_socket_fops = {
 	.owner		= THIS_MODULE,
 	.open		= atalk_seq_socket_open,
 	.read		= seq_read,
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index f949b5c..ec4ebd3 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -784,7 +784,7 @@
 	return seq_open(file, &br2684_seq_ops);
 }
 
-static struct file_operations br2684_proc_ops = {
+static const struct file_operations br2684_proc_ops = {
 	.owner   = THIS_MODULE,
 	.open    = br2684_proc_open,
 	.read    = seq_read,
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 5f8a1d2..ebb5d0c 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -971,7 +971,7 @@
 	goto out;
 }
 
-static struct file_operations arp_seq_fops = {
+static const struct file_operations arp_seq_fops = {
 	.open		= arp_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 57dc2ab..9869455 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1212,7 +1212,7 @@
 	return seq_release_private(inode, file);
 }
 
-static struct file_operations lec_seq_fops = {
+static const struct file_operations lec_seq_fops = {
 	.owner = THIS_MODULE,
 	.open = lec_seq_open,
 	.read = seq_read,
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
index 43315af..4b05cbe 100644
--- a/net/atm/mpoa_proc.c
+++ b/net/atm/mpoa_proc.c
@@ -39,7 +39,7 @@
 /*
  *   Define allowed FILE OPERATIONS
  */
-static struct file_operations mpc_file_operations = {
+static const struct file_operations mpc_file_operations = {
 	.owner =	THIS_MODULE,
 	.open =		proc_mpc_open,
 	.read =		seq_read,
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 190f49c..9e61e51 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -33,7 +33,7 @@
 static ssize_t proc_dev_atm_read(struct file *file,char __user *buf,size_t count,
     loff_t *pos);
 
-static struct file_operations proc_atm_dev_ops = {
+static const struct file_operations proc_atm_dev_ops = {
 	.owner =	THIS_MODULE,
 	.read =		proc_dev_atm_read,
 };
@@ -272,7 +272,7 @@
 	return seq_open(file, &atm_dev_seq_ops);
 }
 
-static struct file_operations devices_seq_fops = {
+static const struct file_operations devices_seq_fops = {
 	.open		= atm_dev_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -307,7 +307,7 @@
 	return __vcc_seq_open(inode, file, PF_ATMPVC, &pvc_seq_ops);
 }
 
-static struct file_operations pvc_seq_fops = {
+static const struct file_operations pvc_seq_fops = {
 	.open		= pvc_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -341,7 +341,7 @@
 	return __vcc_seq_open(inode, file, 0, &vcc_seq_ops);
 }
 
-static struct file_operations vcc_seq_fops = {
+static const struct file_operations vcc_seq_fops = {
 	.open		= vcc_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -376,7 +376,7 @@
 	return __vcc_seq_open(inode, file, PF_ATMSVC, &svc_seq_ops);
 }
 
-static struct file_operations svc_seq_fops = {
+static const struct file_operations svc_seq_fops = {
 	.open		= svc_seq_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -457,7 +457,7 @@
 
 static struct atm_proc_entry {
 	char *name;
-	struct file_operations *proc_fops;
+	const struct file_operations *proc_fops;
 	struct proc_dir_entry *dirent;
 } atm_proc_ents[] = {
 	{ .name = "devices",	.proc_fops = &devices_seq_fops },
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 9a0b677..1c07c6a 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1938,7 +1938,7 @@
 	return seq_open(file, &ax25_info_seqops);
 }
 
-static struct file_operations ax25_info_fops = {
+static const struct file_operations ax25_info_fops = {
 	.owner = THIS_MODULE,
 	.open = ax25_info_open,
 	.read = seq_read,
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 7078861..d65b8e2 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -332,7 +332,7 @@
 	return seq_open(file, &ax25_rt_seqops);
 }
 
-struct file_operations ax25_route_fops = {
+const struct file_operations ax25_route_fops = {
 	.owner = THIS_MODULE,
 	.open = ax25_rt_info_open,
 	.read = seq_read,
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index 7f4c294..59a41b1 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -198,7 +198,7 @@
 	return seq_open(file, &ax25_uid_seqops);
 }
 
-struct file_operations ax25_uid_fops = {
+const struct file_operations ax25_uid_fops = {
 	.owner = THIS_MODULE,
 	.open = ax25_uid_info_open,
 	.read = seq_read,
diff --git a/net/core/dev.c b/net/core/dev.c
index 85d58d7..cf71614 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2200,7 +2200,7 @@
 	return seq_open(file, &dev_seq_ops);
 }
 
-static struct file_operations dev_seq_fops = {
+static const struct file_operations dev_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = dev_seq_open,
 	.read    = seq_read,
@@ -2220,7 +2220,7 @@
 	return seq_open(file, &softnet_seq_ops);
 }
 
-static struct file_operations softnet_seq_fops = {
+static const struct file_operations softnet_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = softnet_seq_open,
 	.read    = seq_read,
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index bfcbdf73a..c4e754e 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -277,7 +277,7 @@
 	return seq_open(file, &dev_mc_seq_ops);
 }
 
-static struct file_operations dev_mc_seq_fops = {
+static const struct file_operations dev_mc_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = dev_mc_seq_open,
 	.read    = seq_read,
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index c08d696..512eed9 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -63,7 +63,7 @@
 
 static struct neigh_table *neigh_tables;
 #ifdef CONFIG_PROC_FS
-static struct file_operations neigh_stat_seq_fops;
+static const struct file_operations neigh_stat_seq_fops;
 #endif
 
 /*
@@ -2403,7 +2403,7 @@
 	return ret;
 };
 
-static struct file_operations neigh_stat_seq_fops = {
+static const struct file_operations neigh_stat_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open 	 = neigh_stat_seq_open,
 	.read	 = seq_read,
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index c2818e0..74a9a32 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -579,7 +579,7 @@
 	return single_open(file, pgctrl_show, PDE(inode)->data);
 }
 
-static struct file_operations pktgen_fops = {
+static const struct file_operations pktgen_fops = {
 	.owner   = THIS_MODULE,
 	.open    = pgctrl_open,
 	.read    = seq_read,
@@ -1672,7 +1672,7 @@
 	return single_open(file, pktgen_if_show, PDE(inode)->data);
 }
 
-static struct file_operations pktgen_if_fops = {
+static const struct file_operations pktgen_if_fops = {
 	.owner   = THIS_MODULE,
 	.open    = pktgen_if_open,
 	.read    = seq_read,
@@ -1815,7 +1815,7 @@
 	return single_open(file, pktgen_thread_show, PDE(inode)->data);
 }
 
-static struct file_operations pktgen_thread_fops = {
+static const struct file_operations pktgen_thread_fops = {
 	.owner   = THIS_MODULE,
 	.open    = pktgen_thread_open,
 	.read    = seq_read,
diff --git a/net/core/sock.c b/net/core/sock.c
index 1e35d99..e9986ac 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1911,7 +1911,7 @@
 	return seq_open(file, &proto_seq_ops);
 }
 
-static struct file_operations proto_seq_fops = {
+static const struct file_operations proto_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= proto_seq_open,
 	.read		= seq_read,
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 64017d4..9936ab1 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -674,7 +674,7 @@
 	return seq_open(file, &wireless_seq_ops);
 }
 
-static struct file_operations wireless_seq_fops = {
+static const struct file_operations wireless_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = wireless_seq_open,
 	.read    = seq_read,
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index f81e37d..3b1f509 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -149,7 +149,7 @@
 	return error ? error : cnt;
 }
 
-static struct file_operations dccpprobe_fops = {
+static const struct file_operations dccpprobe_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = dccpprobe_open,
 	.read    = dccpprobe_read,
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 7006164..c6568d6 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -2331,7 +2331,7 @@
 	goto out;
 }
 
-static struct file_operations dn_socket_seq_fops = {
+static const struct file_operations dn_socket_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= dn_socket_seq_open,
 	.read		= seq_read,
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index c5e2811..2b2c7fe 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -1442,7 +1442,7 @@
 	return seq_open(file, &dn_dev_seq_ops);
 }
 
-static struct file_operations dn_dev_seq_fops = {
+static const struct file_operations dn_dev_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = dn_dev_seq_open,
 	.read	 = seq_read,
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 11d692d..bf701cf 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -598,7 +598,7 @@
 	goto out;
 }
 
-static struct file_operations dn_neigh_seq_fops = {
+static const struct file_operations dn_neigh_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= dn_neigh_seq_open,
 	.read		= seq_read,
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index efccc42..c1b5502 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -1751,7 +1751,7 @@
 	goto out;
 }
 
-static struct file_operations dn_rt_cache_seq_fops = {
+static const struct file_operations dn_rt_cache_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = dn_rt_cache_seq_open,
 	.read	 = seq_read,
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index a58afde..0ffd2d2 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1390,7 +1390,7 @@
 	goto out;
 }
 
-static struct file_operations arp_seq_fops = {
+static const struct file_operations arp_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = arp_seq_open,
 	.read           = seq_read,
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index dea04d7..b21bb28 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -1057,7 +1057,7 @@
 	goto out;
 }
 
-static struct file_operations fib_seq_fops = {
+static const struct file_operations fib_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = fib_seq_open,
 	.read           = seq_read,
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 004a437..c33dca0 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2173,7 +2173,7 @@
 	return single_open(file, fib_triestat_seq_show, NULL);
 }
 
-static struct file_operations fib_triestat_fops = {
+static const struct file_operations fib_triestat_fops = {
 	.owner	= THIS_MODULE,
 	.open	= fib_triestat_seq_open,
 	.read	= seq_read,
@@ -2364,7 +2364,7 @@
 	goto out;
 }
 
-static struct file_operations fib_trie_fops = {
+static const struct file_operations fib_trie_fops = {
 	.owner  = THIS_MODULE,
 	.open   = fib_trie_seq_open,
 	.read   = seq_read,
@@ -2485,7 +2485,7 @@
 	goto out;
 }
 
-static struct file_operations fib_route_fops = {
+static const struct file_operations fib_route_fops = {
 	.owner  = THIS_MODULE,
 	.open   = fib_route_seq_open,
 	.read   = seq_read,
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index b8e1625..0637213 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -2403,7 +2403,7 @@
 	goto out;
 }
 
-static struct file_operations igmp_mc_seq_fops = {
+static const struct file_operations igmp_mc_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	igmp_mc_seq_open,
 	.read		=	seq_read,
@@ -2577,7 +2577,7 @@
 	goto out;
 }
 
-static struct file_operations igmp_mcf_seq_fops = {
+static const struct file_operations igmp_mcf_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	igmp_mcf_seq_open,
 	.read		=	seq_read,
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index ba882be..cf49de1 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -1200,7 +1200,7 @@
 	return single_open(file, pnp_seq_show, NULL);
 }
 
-static struct file_operations pnp_seq_fops = {
+static const struct file_operations pnp_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= pnp_seq_open,
 	.read		= seq_read,
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 604f5b5..e6d11ab 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1712,7 +1712,7 @@
 
 }
 
-static struct file_operations ipmr_vif_fops = {
+static const struct file_operations ipmr_vif_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ipmr_vif_open,
 	.read    = seq_read,
@@ -1874,7 +1874,7 @@
 
 }
 
-static struct file_operations ipmr_mfc_fops = {
+static const struct file_operations ipmr_mfc_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ipmr_mfc_open,
 	.read    = seq_read,
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 6c40899..22e104c 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -561,7 +561,7 @@
 	return seq_open(file, &ip_vs_app_seq_ops);
 }
 
-static struct file_operations ip_vs_app_fops = {
+static const struct file_operations ip_vs_app_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = ip_vs_app_open,
 	.read	 = seq_read,
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 0b5e034..7018f97 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -757,7 +757,7 @@
 	return seq_open(file, &ip_vs_conn_seq_ops);
 }
 
-static struct file_operations ip_vs_conn_fops = {
+static const struct file_operations ip_vs_conn_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ip_vs_conn_open,
 	.read    = seq_read,
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 9b93338..8b08d9c 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -1812,7 +1812,7 @@
 	goto out;
 }
 
-static struct file_operations ip_vs_info_fops = {
+static const struct file_operations ip_vs_info_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = ip_vs_info_open,
 	.read    = seq_read,
@@ -1859,7 +1859,7 @@
 	return single_open(file, ip_vs_stats_show, NULL);
 }
 
-static struct file_operations ip_vs_stats_fops = {
+static const struct file_operations ip_vs_stats_fops = {
 	.owner = THIS_MODULE,
 	.open = ip_vs_stats_seq_open,
 	.read = seq_read,
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 5903588..300ccbb 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -222,7 +222,7 @@
 	return ret;
 }
 
-static struct file_operations ct_file_ops = {
+static const struct file_operations ct_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_open,
 	.read    = seq_read,
@@ -298,7 +298,7 @@
 	return seq_open(file, &exp_seq_ops);
 }
 
-static struct file_operations exp_file_ops = {
+static const struct file_operations exp_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = exp_open,
 	.read    = seq_read,
@@ -386,7 +386,7 @@
 	return seq_open(file, &ct_cpu_seq_ops);
 }
 
-static struct file_operations ct_cpu_seq_fops = {
+static const struct file_operations ct_cpu_seq_fops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_cpu_seq_open,
 	.read    = seq_read,
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 4fe28f2..e965b33 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -70,7 +70,7 @@
 static DEFINE_RWLOCK(clusterip_lock);
 
 #ifdef CONFIG_PROC_FS
-static struct file_operations clusterip_proc_fops;
+static const struct file_operations clusterip_proc_fops;
 static struct proc_dir_entry *clusterip_procdir;
 #endif
 
@@ -715,7 +715,7 @@
 	return size;
 }
 
-static struct file_operations clusterip_proc_fops = {
+static const struct file_operations clusterip_proc_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = clusterip_proc_open,
 	.read	 = seq_read,
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 6b97b67..aecb9c4 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -79,7 +79,7 @@
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry	*proc_dir;
-static struct file_operations	recent_fops;
+static const struct file_operations	recent_fops;
 #endif
 
 static u_int32_t hash_rnd;
@@ -454,7 +454,7 @@
 	return size;
 }
 
-static struct file_operations recent_fops = {
+static const struct file_operations recent_fops = {
 	.open		= recent_seq_open,
 	.read		= seq_read,
 	.write		= recent_proc_write,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 14a93a7..89f933e 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -197,7 +197,7 @@
 	return ret;
 }
 
-static struct file_operations ct_file_ops = {
+static const struct file_operations ct_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_open,
 	.read    = seq_read,
@@ -278,7 +278,7 @@
 	return seq_open(file, &exp_seq_ops);
 }
 
-static struct file_operations ip_exp_file_ops = {
+static const struct file_operations ip_exp_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = exp_open,
 	.read    = seq_read,
@@ -366,7 +366,7 @@
 	return seq_open(file, &ct_cpu_seq_ops);
 }
 
-static struct file_operations ct_cpu_seq_fops = {
+static const struct file_operations ct_cpu_seq_fops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_cpu_seq_open,
 	.read    = seq_read,
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index ccb199e..ae68a69 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -79,7 +79,7 @@
 	return single_open(file, sockstat_seq_show, NULL);
 }
 
-static struct file_operations sockstat_seq_fops = {
+static const struct file_operations sockstat_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = sockstat_seq_open,
 	.read	 = seq_read,
@@ -326,7 +326,7 @@
 	return single_open(file, snmp_seq_show, NULL);
 }
 
-static struct file_operations snmp_seq_fops = {
+static const struct file_operations snmp_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = snmp_seq_open,
 	.read	 = seq_read,
@@ -360,7 +360,7 @@
 	return single_open(file, netstat_seq_show, NULL);
 }
 
-static struct file_operations netstat_seq_fops = {
+static const struct file_operations netstat_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = netstat_seq_open,
 	.read	 = seq_read,
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 931084b..87e9c16 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -916,7 +916,7 @@
 	goto out;
 }
 
-static struct file_operations raw_seq_fops = {
+static const struct file_operations raw_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = raw_seq_open,
 	.read	 = seq_read,
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 5b3834b3..9b5e564 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -393,7 +393,7 @@
 	goto out;
 }
 
-static struct file_operations rt_cache_seq_fops = {
+static const struct file_operations rt_cache_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = rt_cache_seq_open,
 	.read	 = seq_read,
@@ -484,7 +484,7 @@
 	return seq_open(file, &rt_cpu_seq_ops);
 }
 
-static struct file_operations rt_cpu_seq_fops = {
+static const struct file_operations rt_cpu_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = rt_cpu_seq_open,
 	.read	 = seq_read,
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index 41c1578..61f406f2 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -143,7 +143,7 @@
 	return error ? error : cnt;
 }
 
-static struct file_operations tcpprobe_fops = {
+static const struct file_operations tcpprobe_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = tcpprobe_open,
 	.read    = tcpprobe_read,
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 77e56f2..ea0755b 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2776,7 +2776,7 @@
 	goto out;
 }
 
-static struct file_operations if6_fops = {
+static const struct file_operations if6_fops = {
 	.owner		= THIS_MODULE,
 	.open		= if6_seq_open,
 	.read		= seq_read,
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index e2dc1c4..6fb2e9d 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -565,7 +565,7 @@
 	goto out;
 }
 
-static struct file_operations ac6_seq_fops = {
+static const struct file_operations ac6_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	ac6_seq_open,
 	.read		=	seq_read,
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 1551ab3..c206a15 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -677,7 +677,7 @@
 	goto out;
 }
 
-static struct file_operations ip6fl_seq_fops = {
+static const struct file_operations ip6fl_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	ip6fl_seq_open,
 	.read		=	seq_read,
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index c9db5bc..a8d6625 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2451,7 +2451,7 @@
 	goto out;
 }
 
-static struct file_operations igmp6_mc_seq_fops = {
+static const struct file_operations igmp6_mc_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	igmp6_mc_seq_open,
 	.read		=	seq_read,
@@ -2625,7 +2625,7 @@
 	goto out;
 }
 
-static struct file_operations igmp6_mcf_seq_fops = {
+static const struct file_operations igmp6_mcf_seq_fops = {
 	.owner		=	THIS_MODULE,
 	.open		=	igmp6_mcf_seq_open,
 	.read		=	seq_read,
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 032ef95..c82257d 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -187,7 +187,7 @@
 	return single_open(file, sockstat6_seq_show, NULL);
 }
 
-static struct file_operations sockstat6_seq_fops = {
+static const struct file_operations sockstat6_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = sockstat6_seq_open,
 	.read	 = seq_read,
@@ -200,7 +200,7 @@
 	return single_open(file, snmp6_seq_show, PDE(inode)->data);
 }
 
-static struct file_operations snmp6_seq_fops = {
+static const struct file_operations snmp6_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = snmp6_seq_open,
 	.read	 = seq_read,
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 16d4c63..1f8f627 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1273,7 +1273,7 @@
 	goto out;
 }
 
-static struct file_operations raw6_seq_fops = {
+static const struct file_operations raw6_seq_fops = {
 	.owner =	THIS_MODULE,
 	.open =		raw6_seq_open,
 	.read =		seq_read,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index a415ac6..0e1f4b2 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2345,7 +2345,7 @@
 	return single_open(file, rt6_stats_seq_show, NULL);
 }
 
-static struct file_operations rt6_stats_seq_fops = {
+static const struct file_operations rt6_stats_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = rt6_stats_seq_open,
 	.read	 = seq_read,
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
index 811e4ba..db32ac8 100644
--- a/net/ipx/ipx_proc.c
+++ b/net/ipx/ipx_proc.c
@@ -322,7 +322,7 @@
 	return seq_open(file, &ipx_seq_socket_ops);
 }
 
-static struct file_operations ipx_seq_interface_fops = {
+static const struct file_operations ipx_seq_interface_fops = {
 	.owner		= THIS_MODULE,
 	.open           = ipx_seq_interface_open,
 	.read           = seq_read,
@@ -330,7 +330,7 @@
 	.release        = seq_release,
 };
 
-static struct file_operations ipx_seq_route_fops = {
+static const struct file_operations ipx_seq_route_fops = {
 	.owner		= THIS_MODULE,
 	.open           = ipx_seq_route_open,
 	.read           = seq_read,
@@ -338,7 +338,7 @@
 	.release        = seq_release,
 };
 
-static struct file_operations ipx_seq_socket_fops = {
+static const struct file_operations ipx_seq_socket_fops = {
 	.owner		= THIS_MODULE,
 	.open           = ipx_seq_socket_open,
 	.read           = seq_read,
diff --git a/net/irda/discovery.c b/net/irda/discovery.c
index 789478b..f097341 100644
--- a/net/irda/discovery.c
+++ b/net/irda/discovery.c
@@ -409,7 +409,7 @@
 	return seq_open(file, &discovery_seq_ops);
 }
 
-struct file_operations discovery_seq_fops = {
+const struct file_operations discovery_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = discovery_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index c28ee7b..ec40715 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -56,7 +56,7 @@
 extern struct proc_dir_entry *proc_irda;
 static int ircomm_seq_open(struct inode *, struct file *);
 
-static struct file_operations ircomm_proc_fops = {
+static const struct file_operations ircomm_proc_fops = {
 	.owner		= THIS_MODULE,
 	.open           = ircomm_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 98b0fa9..915d938 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -1080,7 +1080,7 @@
 	return seq_open(file, &irias_seq_ops);
 }
 
-struct file_operations irias_seq_fops = {
+const struct file_operations irias_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = irias_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index 9c3dc57..fcf9d65 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -93,7 +93,7 @@
 
 static int irlan_seq_open(struct inode *inode, struct file *file);
 
-static struct file_operations irlan_fops = {
+static const struct file_operations irlan_fops = {
 	.owner	 = THIS_MODULE,
 	.open    = irlan_seq_open,
 	.read    = seq_read,
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index fd73e4a..d93ebd1 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -1244,7 +1244,7 @@
 	goto out;
 }
 
-struct file_operations irlap_seq_fops = {
+const struct file_operations irlap_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = irlap_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index b134c3c..9df0461 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -2026,7 +2026,7 @@
 	goto out;
 }
 
-struct file_operations irlmp_seq_fops = {
+const struct file_operations irlmp_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = irlmp_seq_open,
 	.read           = seq_read,
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 6883635..a7486b3 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -1895,7 +1895,7 @@
 	goto out;
 }
 
-struct file_operations irttp_seq_fops = {
+const struct file_operations irttp_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open           = irttp_seq_open,
 	.read           = seq_read,
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
index dcfe6c7..3ab9d9f 100644
--- a/net/llc/llc_proc.c
+++ b/net/llc/llc_proc.c
@@ -208,7 +208,7 @@
 	return seq_open(file, &llc_seq_core_ops);
 }
 
-static struct file_operations llc_seq_socket_fops = {
+static const struct file_operations llc_seq_socket_fops = {
 	.owner		= THIS_MODULE,
 	.open		= llc_seq_socket_open,
 	.read		= seq_read,
@@ -216,7 +216,7 @@
 	.release	= seq_release,
 };
 
-static struct file_operations llc_seq_core_fops = {
+static const struct file_operations llc_seq_core_fops = {
 	.owner		= THIS_MODULE,
 	.open		= llc_seq_core_open,
 	.read		= seq_read,
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 9cbf926..5cdcd7f 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -435,7 +435,7 @@
 	return seq_open(file, &exp_seq_ops);
 }
 
-struct file_operations exp_file_ops = {
+const struct file_operations exp_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = exp_open,
 	.read    = seq_read,
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index f1cb60f..04ac124 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -229,7 +229,7 @@
 	return ret;
 }
 
-static struct file_operations ct_file_ops = {
+static const struct file_operations ct_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_open,
 	.read    = seq_read,
@@ -317,7 +317,7 @@
 	return seq_open(file, &ct_cpu_seq_ops);
 }
 
-static struct file_operations ct_cpu_seq_fops = {
+static const struct file_operations ct_cpu_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = ct_cpu_seq_open,
 	.read	 = seq_read,
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 8901b3a..07e28e0 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -151,7 +151,7 @@
 	return seq_open(file, &nflog_seq_ops);
 }
 
-static struct file_operations nflog_file_ops = {
+static const struct file_operations nflog_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = nflog_open,
 	.read	 = seq_read,
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 4d8936e..e136fea 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -331,7 +331,7 @@
 	return seq_open(file, &nfqueue_seq_ops);
 }
 
-static struct file_operations nfqueue_file_ops = {
+static const struct file_operations nfqueue_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = nfqueue_open,
 	.read	 = seq_read,
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index d1505dd..c47e7e2 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -1025,7 +1025,7 @@
 	return ret;
 }
 
-static struct file_operations nful_file_ops = {
+static const struct file_operations nful_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = nful_open,
 	.read	 = seq_read,
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index a88a017..99e516e 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -1077,7 +1077,7 @@
 	return ret;
 }
 
-static struct file_operations nfqnl_file_ops = {
+static const struct file_operations nfqnl_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = nfqnl_open,
 	.read	 = seq_read,
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8996584..134cc88 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -772,7 +772,7 @@
 	return ret;
 }
 
-static struct file_operations xt_file_ops = {
+static const struct file_operations xt_file_ops = {
 	.owner	 = THIS_MODULE,
 	.open	 = xt_tgt_open,
 	.read	 = seq_read,
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index bd1f7a2..269a1e7 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -37,7 +37,7 @@
 /* need to declare this at the top */
 static struct proc_dir_entry *hashlimit_procdir4;
 static struct proc_dir_entry *hashlimit_procdir6;
-static struct file_operations dl_file_ops;
+static const struct file_operations dl_file_ops;
 
 /* hash table crap */
 struct dsthash_dst {
@@ -714,7 +714,7 @@
 	return ret;
 }
 
-static struct file_operations dl_file_ops = {
+static const struct file_operations dl_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = dl_proc_open,
 	.read    = seq_read,
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index f6ee9b4..e73d8f5 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1713,7 +1713,7 @@
 	return 0;
 }
 
-static struct file_operations netlink_seq_fops = {
+static const struct file_operations netlink_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= netlink_seq_open,
 	.read		= seq_read,
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 799b768..bf9837d 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1335,7 +1335,7 @@
 	return seq_open(file, &nr_info_seqops);
 }
 
-static struct file_operations nr_info_fops = {
+static const struct file_operations nr_info_fops = {
 	.owner = THIS_MODULE,
 	.open = nr_info_open,
 	.read = seq_read,
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index e9909ae..c2fbac9 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -934,7 +934,7 @@
 	return seq_open(file, &nr_node_seqops);
 }
 
-struct file_operations nr_nodes_fops = {
+const struct file_operations nr_nodes_fops = {
 	.owner = THIS_MODULE,
 	.open = nr_node_info_open,
 	.read = seq_read,
@@ -1018,7 +1018,7 @@
 	return seq_open(file, &nr_neigh_seqops);
 }
 
-struct file_operations nr_neigh_fops = {
+const struct file_operations nr_neigh_fops = {
 	.owner = THIS_MODULE,
 	.open = nr_neigh_info_open,
 	.read = seq_read,
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 4445509..15ff7b1 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1952,7 +1952,7 @@
 	return seq_open(file, &packet_seq_ops);
 }
 
-static struct file_operations packet_seq_fops = {
+static const struct file_operations packet_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= packet_seq_open,
 	.read		= seq_read,
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 7a81a8e..8c34f1c 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1440,7 +1440,7 @@
 	return seq_open(file, &rose_info_seqops);
 }
 
-static struct file_operations rose_info_fops = {
+static const struct file_operations rose_info_fops = {
 	.owner = THIS_MODULE,
 	.open = rose_info_open,
 	.read = seq_read,
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 0dcca42..1ddf7f5 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -1129,7 +1129,7 @@
 	return seq_open(file, &rose_node_seqops);
 }
 
-struct file_operations rose_nodes_fops = {
+const struct file_operations rose_nodes_fops = {
 	.owner = THIS_MODULE,
 	.open = rose_nodes_open,
 	.read = seq_read,
@@ -1211,7 +1211,7 @@
 	return seq_open(file, &rose_neigh_seqops);
 }
 
-struct file_operations rose_neigh_fops = {
+const struct file_operations rose_neigh_fops = {
 	.owner = THIS_MODULE,
 	.open = rose_neigh_open,
 	.read = seq_read,
@@ -1295,7 +1295,7 @@
 	return seq_open(file, &rose_route_seqops);
 }
 
-struct file_operations rose_routes_fops = {
+const struct file_operations rose_routes_fops = {
 	.owner = THIS_MODULE,
 	.open = rose_route_open,
 	.read = seq_read,
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 29975d9..8551c87 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -37,7 +37,7 @@
 	.show	= rxrpc_proc_transports_show,
 };
 
-static struct file_operations rxrpc_proc_transports_fops = {
+static const struct file_operations rxrpc_proc_transports_fops = {
 	.open		= rxrpc_proc_transports_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -57,7 +57,7 @@
 	.show	= rxrpc_proc_peers_show,
 };
 
-static struct file_operations rxrpc_proc_peers_fops = {
+static const struct file_operations rxrpc_proc_peers_fops = {
 	.open		= rxrpc_proc_peers_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -77,7 +77,7 @@
 	.show	= rxrpc_proc_conns_show,
 };
 
-static struct file_operations rxrpc_proc_conns_fops = {
+static const struct file_operations rxrpc_proc_conns_fops = {
 	.open		= rxrpc_proc_conns_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -97,7 +97,7 @@
 	.show	= rxrpc_proc_calls_show,
 };
 
-static struct file_operations rxrpc_proc_calls_fops = {
+static const struct file_operations rxrpc_proc_calls_fops = {
 	.open		= rxrpc_proc_calls_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 60b92fc..4158127 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1194,7 +1194,7 @@
 	return single_open(file, psched_show, PDE(inode)->data);
 }
 
-static struct file_operations psched_fops = {
+static const struct file_operations psched_fops = {
 	.owner = THIS_MODULE,
 	.open = psched_open,
 	.read  = seq_read,
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index e93fc1c..2f12bf2 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -114,7 +114,7 @@
 	return single_open(file, sctp_snmp_seq_show, NULL);
 }
 
-static struct file_operations sctp_snmp_seq_fops = {
+static const struct file_operations sctp_snmp_seq_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = sctp_snmp_seq_open,
 	.read	 = seq_read,
@@ -264,7 +264,7 @@
 	return seq_open(file, &sctp_eps_ops);
 }
 
-static struct file_operations sctp_eps_seq_fops = {
+static const struct file_operations sctp_eps_seq_fops = {
 	.open	 = sctp_eps_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
@@ -374,7 +374,7 @@
 	return seq_open(file, &sctp_assoc_ops);
 }
 
-static struct file_operations sctp_assocs_seq_fops = {
+static const struct file_operations sctp_assocs_seq_fops = {
 	.open	 = sctp_assocs_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
diff --git a/net/socket.c b/net/socket.c
index a92f595..0778c54 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -117,7 +117,7 @@
  *	in the operation structures but are done directly via the socketcall() multiplexor.
  */
 
-static struct file_operations socket_file_ops = {
+static const struct file_operations socket_file_ops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.aio_read =	sock_aio_read,
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index c80df45..8612044 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -282,9 +282,9 @@
 static struct cache_detail *current_detail;
 static int current_index;
 
-static struct file_operations cache_file_operations;
-static struct file_operations content_file_operations;
-static struct file_operations cache_flush_operations;
+static const struct file_operations cache_file_operations;
+static const struct file_operations content_file_operations;
+static const struct file_operations cache_flush_operations;
 
 static void do_cache_clean(struct work_struct *work);
 static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean);
@@ -887,7 +887,7 @@
 
 
 
-static struct file_operations cache_file_operations = {
+static const struct file_operations cache_file_operations = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= cache_read,
@@ -1245,7 +1245,7 @@
 	return seq_release(inode, file);
 }
 
-static struct file_operations content_file_operations = {
+static const struct file_operations content_file_operations = {
 	.open		= content_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -1297,7 +1297,7 @@
 	return count;
 }
 
-static struct file_operations cache_flush_operations = {
+static const struct file_operations cache_flush_operations = {
 	.open		= nonseekable_open,
 	.read		= read_flush,
 	.write		= write_flush,
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 89273d3..e1fad77 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -309,7 +309,7 @@
 	}
 }
 
-static struct file_operations rpc_pipe_fops = {
+static const struct file_operations rpc_pipe_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= rpc_pipe_read,
@@ -366,7 +366,7 @@
 	return single_release(inode, file);
 }
 
-static struct file_operations rpc_info_operations = {
+static const struct file_operations rpc_info_operations = {
 	.owner		= THIS_MODULE,
 	.open		= rpc_info_open,
 	.read		= seq_read,
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index bd98124..044d948 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -66,7 +66,7 @@
 	return single_open(file, rpc_proc_show, PDE(inode)->data);
 }
 
-static struct file_operations rpc_proc_fops = {
+static const struct file_operations rpc_proc_fops = {
 	.owner = THIS_MODULE,
 	.open = rpc_proc_open,
 	.read  = seq_read,
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 987244f..4b775db 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -421,6 +421,7 @@
 static int
 svcauth_unix_set_client(struct svc_rqst *rqstp)
 {
+	struct sockaddr_in *sin = svc_addr_in(rqstp);
 	struct ip_map *ipm;
 
 	rqstp->rq_client = NULL;
@@ -430,7 +431,7 @@
 	ipm = ip_map_cached_get(rqstp);
 	if (ipm == NULL)
 		ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
-				    rqstp->rq_addr.sin_addr);
+				    sin->sin_addr);
 
 	if (ipm == NULL)
 		return SVC_DENIED;
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 2fd0ba2..63ae947 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -36,11 +36,13 @@
 #include <net/sock.h>
 #include <net/checksum.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <net/tcp_states.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
 #include <linux/sunrpc/types.h>
+#include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/stats.h>
@@ -75,7 +77,7 @@
 
 
 static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
-					 int *errp, int pmap_reg);
+					 int *errp, int flags);
 static void		svc_delete_socket(struct svc_sock *svsk);
 static void		svc_udp_data_ready(struct sock *, int);
 static int		svc_udp_recvfrom(struct svc_rqst *);
@@ -121,6 +123,41 @@
 }
 #endif
 
+static char *__svc_print_addr(struct sockaddr *addr, char *buf, size_t len)
+{
+	switch (addr->sa_family) {
+	case AF_INET:
+		snprintf(buf, len, "%u.%u.%u.%u, port=%u",
+			NIPQUAD(((struct sockaddr_in *) addr)->sin_addr),
+			htons(((struct sockaddr_in *) addr)->sin_port));
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x, port=%u",
+			NIP6(((struct sockaddr_in6 *) addr)->sin6_addr),
+			htons(((struct sockaddr_in6 *) addr)->sin6_port));
+		break;
+#endif
+	default:
+		snprintf(buf, len, "unknown address type: %d", addr->sa_family);
+		break;
+	}
+	return buf;
+}
+
+/**
+ * svc_print_addr - Format rq_addr field for printing
+ * @rqstp: svc_rqst struct containing address to print
+ * @buf: target buffer for formatted address
+ * @len: length of target buffer
+ *
+ */
+char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len)
+{
+	return __svc_print_addr(svc_addr(rqstp), buf, len);
+}
+EXPORT_SYMBOL_GPL(svc_print_addr);
+
 /*
  * Queue up an idle server thread.  Must have pool->sp_lock held.
  * Note: this is really a stack rather than a queue, so that we only
@@ -410,6 +447,43 @@
 	}
 }
 
+union svc_pktinfo_u {
+	struct in_pktinfo pkti;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	struct in6_pktinfo pkti6;
+#endif
+};
+
+static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh)
+{
+	switch (rqstp->rq_sock->sk_sk->sk_family) {
+	case AF_INET: {
+			struct in_pktinfo *pki = CMSG_DATA(cmh);
+
+			cmh->cmsg_level = SOL_IP;
+			cmh->cmsg_type = IP_PKTINFO;
+			pki->ipi_ifindex = 0;
+			pki->ipi_spec_dst.s_addr = rqstp->rq_daddr.addr.s_addr;
+			cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+		}
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6: {
+			struct in6_pktinfo *pki = CMSG_DATA(cmh);
+
+			cmh->cmsg_level = SOL_IPV6;
+			cmh->cmsg_type = IPV6_PKTINFO;
+			pki->ipi6_ifindex = 0;
+			ipv6_addr_copy(&pki->ipi6_addr,
+					&rqstp->rq_daddr.addr6);
+			cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
+		}
+		break;
+#endif
+	}
+	return;
+}
+
 /*
  * Generic sendto routine
  */
@@ -419,9 +493,8 @@
 	struct svc_sock	*svsk = rqstp->rq_sock;
 	struct socket	*sock = svsk->sk_sock;
 	int		slen;
-	char 		buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
+	char 		buffer[CMSG_SPACE(sizeof(union svc_pktinfo_u))];
 	struct cmsghdr *cmh = (struct cmsghdr *)buffer;
-	struct in_pktinfo *pki = (struct in_pktinfo *)CMSG_DATA(cmh);
 	int		len = 0;
 	int		result;
 	int		size;
@@ -429,25 +502,20 @@
 	size_t		base = xdr->page_base;
 	unsigned int	pglen = xdr->page_len;
 	unsigned int	flags = MSG_MORE;
+	char		buf[RPC_MAX_ADDRBUFLEN];
 
 	slen = xdr->len;
 
 	if (rqstp->rq_prot == IPPROTO_UDP) {
-		/* set the source and destination */
-		struct msghdr	msg;
-		msg.msg_name    = &rqstp->rq_addr;
-		msg.msg_namelen = sizeof(rqstp->rq_addr);
-		msg.msg_iov     = NULL;
-		msg.msg_iovlen  = 0;
-		msg.msg_flags	= MSG_MORE;
+		struct msghdr msg = {
+			.msg_name	= &rqstp->rq_addr,
+			.msg_namelen	= rqstp->rq_addrlen,
+			.msg_control	= cmh,
+			.msg_controllen	= sizeof(buffer),
+			.msg_flags	= MSG_MORE,
+		};
 
-		msg.msg_control = cmh;
-		msg.msg_controllen = sizeof(buffer);
-		cmh->cmsg_len = CMSG_LEN(sizeof(*pki));
-		cmh->cmsg_level = SOL_IP;
-		cmh->cmsg_type = IP_PKTINFO;
-		pki->ipi_ifindex = 0;
-		pki->ipi_spec_dst.s_addr = rqstp->rq_daddr;
+		svc_set_cmsg_data(rqstp, cmh);
 
 		if (sock_sendmsg(sock, &msg, 0) < 0)
 			goto out;
@@ -491,9 +559,9 @@
 			len += result;
 	}
 out:
-	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %x)\n",
-			rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len, xdr->len, len,
-		rqstp->rq_addr.sin_addr.s_addr);
+	dprintk("svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s)\n",
+		rqstp->rq_sock, xdr->head[0].iov_base, xdr->head[0].iov_len,
+		xdr->len, len, svc_print_addr(rqstp, buf, sizeof(buf)));
 
 	return len;
 }
@@ -568,31 +636,22 @@
 static int
 svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
 {
-	struct msghdr	msg;
-	struct socket	*sock;
-	int		len, alen;
+	struct svc_sock *svsk = rqstp->rq_sock;
+	struct msghdr msg = {
+		.msg_flags	= MSG_DONTWAIT,
+	};
+	int len;
 
-	rqstp->rq_addrlen = sizeof(rqstp->rq_addr);
-	sock = rqstp->rq_sock->sk_sock;
-
-	msg.msg_name    = &rqstp->rq_addr;
-	msg.msg_namelen = sizeof(rqstp->rq_addr);
-	msg.msg_control = NULL;
-	msg.msg_controllen = 0;
-
-	msg.msg_flags	= MSG_DONTWAIT;
-
-	len = kernel_recvmsg(sock, &msg, iov, nr, buflen, MSG_DONTWAIT);
+	len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
+				msg.msg_flags);
 
 	/* sock_recvmsg doesn't fill in the name/namelen, so we must..
-	 * possibly we should cache this in the svc_sock structure
-	 * at accept time. FIXME
 	 */
-	alen = sizeof(rqstp->rq_addr);
-	kernel_getpeername(sock, (struct sockaddr *)&rqstp->rq_addr, &alen);
+	memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen);
+	rqstp->rq_addrlen = svsk->sk_remotelen;
 
 	dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
-		rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len);
+		svsk, iov[0].iov_base, iov[0].iov_len, len);
 
 	return len;
 }
@@ -662,6 +721,47 @@
 	}
 }
 
+static void svc_udp_get_sender_address(struct svc_rqst *rqstp,
+					struct sk_buff *skb)
+{
+	switch (rqstp->rq_sock->sk_sk->sk_family) {
+	case AF_INET: {
+		/* this seems to come from net/ipv4/udp.c:udp_recvmsg */
+			struct sockaddr_in *sin = svc_addr_in(rqstp);
+
+			sin->sin_family = AF_INET;
+			sin->sin_port = skb->h.uh->source;
+			sin->sin_addr.s_addr = skb->nh.iph->saddr;
+			rqstp->rq_addrlen = sizeof(struct sockaddr_in);
+			/* Remember which interface received this request */
+			rqstp->rq_daddr.addr.s_addr = skb->nh.iph->daddr;
+		}
+		break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6: {
+		/* this is derived from net/ipv6/udp.c:udpv6_recvmesg */
+			struct sockaddr_in6 *sin6 = svc_addr_in6(rqstp);
+
+			sin6->sin6_family = AF_INET6;
+			sin6->sin6_port = skb->h.uh->source;
+			sin6->sin6_flowinfo = 0;
+			sin6->sin6_scope_id = 0;
+			if (ipv6_addr_type(&sin6->sin6_addr) &
+							IPV6_ADDR_LINKLOCAL)
+				sin6->sin6_scope_id = IP6CB(skb)->iif;
+			ipv6_addr_copy(&sin6->sin6_addr,
+							&skb->nh.ipv6h->saddr);
+			rqstp->rq_addrlen = sizeof(struct sockaddr_in);
+			/* Remember which interface received this request */
+			ipv6_addr_copy(&rqstp->rq_daddr.addr6,
+							&skb->nh.ipv6h->saddr);
+		}
+		break;
+#endif
+	}
+	return;
+}
+
 /*
  * Receive a datagram from a UDP socket.
  */
@@ -725,13 +825,9 @@
 	len  = skb->len - sizeof(struct udphdr);
 	rqstp->rq_arg.len = len;
 
-	rqstp->rq_prot        = IPPROTO_UDP;
+	rqstp->rq_prot = IPPROTO_UDP;
 
-	/* Get sender address */
-	rqstp->rq_addr.sin_family = AF_INET;
-	rqstp->rq_addr.sin_port = skb->h.uh->source;
-	rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr;
-	rqstp->rq_daddr = skb->nh.iph->daddr;
+	svc_udp_get_sender_address(rqstp, skb);
 
 	if (skb_is_nonlinear(skb)) {
 		/* we have to copy */
@@ -875,18 +971,36 @@
 		wake_up_interruptible(sk->sk_sleep);
 }
 
+static inline int svc_port_is_privileged(struct sockaddr *sin)
+{
+	switch (sin->sa_family) {
+	case AF_INET:
+		return ntohs(((struct sockaddr_in *)sin)->sin_port)
+			< PROT_SOCK;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+	case AF_INET6:
+		return ntohs(((struct sockaddr_in6 *)sin)->sin6_port)
+			< PROT_SOCK;
+#endif
+	default:
+		return 0;
+	}
+}
+
 /*
  * Accept a TCP connection
  */
 static void
 svc_tcp_accept(struct svc_sock *svsk)
 {
-	struct sockaddr_in sin;
+	struct sockaddr_storage addr;
+	struct sockaddr	*sin = (struct sockaddr *) &addr;
 	struct svc_serv	*serv = svsk->sk_server;
 	struct socket	*sock = svsk->sk_sock;
 	struct socket	*newsock;
 	struct svc_sock	*newsvsk;
 	int		err, slen;
+	char		buf[RPC_MAX_ADDRBUFLEN];
 
 	dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
 	if (!sock)
@@ -907,8 +1021,7 @@
 	set_bit(SK_CONN, &svsk->sk_flags);
 	svc_sock_enqueue(svsk);
 
-	slen = sizeof(sin);
-	err = kernel_getpeername(newsock, (struct sockaddr *) &sin, &slen);
+	err = kernel_getpeername(newsock, sin, &slen);
 	if (err < 0) {
 		if (net_ratelimit())
 			printk(KERN_WARNING "%s: peername failed (err %d)!\n",
@@ -917,27 +1030,30 @@
 	}
 
 	/* Ideally, we would want to reject connections from unauthorized
-	 * hosts here, but when we get encription, the IP of the host won't
-	 * tell us anything. For now just warn about unpriv connections.
+	 * hosts here, but when we get encryption, the IP of the host won't
+	 * tell us anything.  For now just warn about unpriv connections.
 	 */
-	if (ntohs(sin.sin_port) >= 1024) {
+	if (!svc_port_is_privileged(sin)) {
 		dprintk(KERN_WARNING
-			"%s: connect from unprivileged port: %u.%u.%u.%u:%d\n",
+			"%s: connect from unprivileged port: %s\n",
 			serv->sv_name,
-			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+			__svc_print_addr(sin, buf, sizeof(buf)));
 	}
-
-	dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
-			NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+	dprintk("%s: connect from %s\n", serv->sv_name,
+		__svc_print_addr(sin, buf, sizeof(buf)));
 
 	/* make sure that a write doesn't block forever when
 	 * low on memory
 	 */
 	newsock->sk->sk_sndtimeo = HZ*30;
 
-	if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
+	if (!(newsvsk = svc_setup_socket(serv, newsock, &err,
+				 (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY))))
 		goto failed;
+	memcpy(&newsvsk->sk_remote, sin, slen);
+	newsvsk->sk_remotelen = slen;
 
+	svc_sock_received(newsvsk);
 
 	/* make sure that we don't have too many active connections.
 	 * If we have, something must be dropped.
@@ -960,11 +1076,9 @@
 					"sockets, consider increasing the "
 					"number of nfsd threads\n",
 						   serv->sv_name);
-				printk(KERN_NOTICE "%s: last TCP connect from "
-					"%u.%u.%u.%u:%d\n",
-					serv->sv_name,
-					NIPQUAD(sin.sin_addr.s_addr),
-					ntohs(sin.sin_port));
+				printk(KERN_NOTICE
+				       "%s: last TCP connect from %s\n",
+				       serv->sv_name, buf);
 			}
 			/*
 			 * Always select the oldest socket. It's not fair,
@@ -1266,7 +1380,7 @@
 int
 svc_recv(struct svc_rqst *rqstp, long timeout)
 {
-	struct svc_sock		*svsk =NULL;
+	struct svc_sock		*svsk = NULL;
 	struct svc_serv		*serv = rqstp->rq_server;
 	struct svc_pool		*pool = rqstp->rq_pool;
 	int			len, i;
@@ -1363,7 +1477,7 @@
 	svsk->sk_lastrecv = get_seconds();
 	clear_bit(SK_OLD, &svsk->sk_flags);
 
-	rqstp->rq_secure  = ntohs(rqstp->rq_addr.sin_port) < 1024;
+	rqstp->rq_secure = svc_port_is_privileged(svc_addr(rqstp));
 	rqstp->rq_chandle.defer = svc_defer;
 
 	if (serv->sv_stats)
@@ -1476,12 +1590,14 @@
  * Initialize socket for RPC use and create svc_sock struct
  * XXX: May want to setsockopt SO_SNDBUF and SO_RCVBUF.
  */
-static struct svc_sock *
-svc_setup_socket(struct svc_serv *serv, struct socket *sock,
-					int *errp, int pmap_register)
+static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
+						struct socket *sock,
+						int *errp, int flags)
 {
 	struct svc_sock	*svsk;
 	struct sock	*inet;
+	int		pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
+	int		is_temporary = flags & SVC_SOCK_TEMPORARY;
 
 	dprintk("svc: svc_setup_socket %p\n", sock);
 	if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
@@ -1523,7 +1639,7 @@
 		svc_tcp_init(svsk);
 
 	spin_lock_bh(&serv->sv_lock);
-	if (!pmap_register) {
+	if (is_temporary) {
 		set_bit(SK_TEMP, &svsk->sk_flags);
 		list_add(&svsk->sk_list, &serv->sv_tempsocks);
 		serv->sv_tmpcnt++;
@@ -1543,8 +1659,6 @@
 	dprintk("svc: svc_setup_socket created %p (inet %p)\n",
 				svsk, svsk->sk_sk);
 
-	clear_bit(SK_BUSY, &svsk->sk_flags);
-	svc_sock_enqueue(svsk);
 	return svsk;
 }
 
@@ -1567,9 +1681,11 @@
 	else if (so->state > SS_UNCONNECTED)
 		err = -EISCONN;
 	else {
-		svsk = svc_setup_socket(serv, so, &err, 1);
-		if (svsk)
+		svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS);
+		if (svsk) {
+			svc_sock_received(svsk);
 			err = 0;
+		}
 	}
 	if (err) {
 		sockfd_put(so);
@@ -1583,18 +1699,18 @@
 /*
  * Create socket for RPC service.
  */
-static int
-svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
+static int svc_create_socket(struct svc_serv *serv, int protocol,
+				struct sockaddr *sin, int len, int flags)
 {
 	struct svc_sock	*svsk;
 	struct socket	*sock;
 	int		error;
 	int		type;
+	char		buf[RPC_MAX_ADDRBUFLEN];
 
-	dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n",
-				serv->sv_program->pg_name, protocol,
-				NIPQUAD(sin->sin_addr.s_addr),
-				ntohs(sin->sin_port));
+	dprintk("svc: svc_create_socket(%s, %d, %s)\n",
+			serv->sv_program->pg_name, protocol,
+			__svc_print_addr(sin, buf, sizeof(buf)));
 
 	if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
 		printk(KERN_WARNING "svc: only UDP and TCP "
@@ -1603,15 +1719,15 @@
 	}
 	type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
 
-	if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
+	error = sock_create_kern(sin->sa_family, type, protocol, &sock);
+	if (error < 0)
 		return error;
 
 	svc_reclassify_socket(sock);
 
 	if (type == SOCK_STREAM)
-		sock->sk->sk_reuse = 1; /* allow address reuse */
-	error = kernel_bind(sock, (struct sockaddr *) sin,
-					sizeof(*sin));
+		sock->sk->sk_reuse = 1;		/* allow address reuse */
+	error = kernel_bind(sock, sin, len);
 	if (error < 0)
 		goto bummer;
 
@@ -1620,8 +1736,10 @@
 			goto bummer;
 	}
 
-	if ((svsk = svc_setup_socket(serv, sock, &error, 1)) != NULL)
-		return 0;
+	if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) {
+		svc_sock_received(svsk);
+		return ntohs(inet_sk(svsk->sk_sk)->sport);
+	}
 
 bummer:
 	dprintk("svc: svc_create_socket error = %d\n", -error);
@@ -1681,19 +1799,26 @@
 	svc_sock_put(svsk);
 }
 
-/*
- * Make a socket for nfsd and lockd
+/**
+ * svc_makesock - Make a socket for nfsd and lockd
+ * @serv: RPC server structure
+ * @protocol: transport protocol to use
+ * @port: port to use
+ * @flags: requested socket characteristics
+ *
  */
-int
-svc_makesock(struct svc_serv *serv, int protocol, unsigned short port)
+int svc_makesock(struct svc_serv *serv, int protocol, unsigned short port,
+			int flags)
 {
-	struct sockaddr_in	sin;
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+		.sin_addr.s_addr	= INADDR_ANY,
+		.sin_port		= htons(port),
+	};
 
 	dprintk("svc: creating socket proto = %d\n", protocol);
-	sin.sin_family      = AF_INET;
-	sin.sin_addr.s_addr = INADDR_ANY;
-	sin.sin_port        = htons(port);
-	return svc_create_socket(serv, protocol, &sin);
+	return svc_create_socket(serv, protocol, (struct sockaddr *) &sin,
+							sizeof(sin), flags);
 }
 
 /*
@@ -1742,7 +1867,8 @@
 
 		dr->handle.owner = rqstp->rq_server;
 		dr->prot = rqstp->rq_prot;
-		dr->addr = rqstp->rq_addr;
+		memcpy(&dr->addr, &rqstp->rq_addr, rqstp->rq_addrlen);
+		dr->addrlen = rqstp->rq_addrlen;
 		dr->daddr = rqstp->rq_daddr;
 		dr->argslen = rqstp->rq_arg.len >> 2;
 		memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
@@ -1766,7 +1892,8 @@
 	rqstp->rq_arg.page_len = 0;
 	rqstp->rq_arg.len = dr->argslen<<2;
 	rqstp->rq_prot        = dr->prot;
-	rqstp->rq_addr        = dr->addr;
+	memcpy(&rqstp->rq_addr, &dr->addr, dr->addrlen);
+	rqstp->rq_addrlen     = dr->addrlen;
 	rqstp->rq_daddr       = dr->daddr;
 	rqstp->rq_respages    = rqstp->rq_pages;
 	return dr->argslen<<2;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index ac9478d..6069716 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2040,7 +2040,7 @@
 	goto out;
 }
 
-static struct file_operations unix_seq_fops = {
+static const struct file_operations unix_seq_fops = {
 	.owner		= THIS_MODULE,
 	.open		= unix_seq_open,
 	.read		= seq_read,
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c
index abce828..2051065 100644
--- a/net/wanrouter/wanproc.c
+++ b/net/wanrouter/wanproc.c
@@ -188,7 +188,7 @@
 	return seq_open(file, &status_op);
 }
 
-static struct file_operations config_fops = {
+static const struct file_operations config_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = config_open,
 	.read	 = seq_read,
@@ -196,7 +196,7 @@
 	.release = seq_release,
 };
 
-static struct file_operations status_fops = {
+static const struct file_operations status_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = status_open,
 	.read	 = seq_read,
@@ -271,7 +271,7 @@
 	return single_open(file, wandev_show, PDE(inode)->data);
 }
 
-static struct file_operations wandev_fops = {
+static const struct file_operations wandev_fops = {
 	.owner	 = THIS_MODULE,
 	.open	 = wandev_open,
 	.read	 = seq_read,
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c
index 3c9f1ba..96001f0 100644
--- a/net/x25/x25_proc.c
+++ b/net/x25/x25_proc.c
@@ -270,7 +270,7 @@
 	return seq_open(file, &x25_seq_forward_ops);
 }
 
-static struct file_operations x25_seq_socket_fops = {
+static const struct file_operations x25_seq_socket_fops = {
 	.owner		= THIS_MODULE,
 	.open		= x25_seq_socket_open,
 	.read		= seq_read,
@@ -278,7 +278,7 @@
 	.release	= seq_release,
 };
 
-static struct file_operations x25_seq_route_fops = {
+static const struct file_operations x25_seq_route_fops = {
 	.owner		= THIS_MODULE,
 	.open		= x25_seq_route_open,
 	.read		= seq_read,
diff --git a/security/inode.c b/security/inode.c
index 9b16e14..d7ecf89 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -50,7 +50,7 @@
 	return 0;
 }
 
-static struct file_operations default_file_ops = {
+static const struct file_operations default_file_ops = {
 	.read =		default_read_file,
 	.write =	default_write_file,
 	.open =		default_open,
@@ -215,7 +215,7 @@
  */
 struct dentry *securityfs_create_file(const char *name, mode_t mode,
 				   struct dentry *parent, void *data,
-				   struct file_operations *fops)
+				   const struct file_operations *fops)
 {
 	struct dentry *dentry = NULL;
 	int error;
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 686a9ee..3e0d0a6 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -33,7 +33,7 @@
 	.show	= proc_keys_show,
 };
 
-static struct file_operations proc_keys_fops = {
+static const struct file_operations proc_keys_fops = {
 	.open		= proc_keys_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
@@ -54,7 +54,7 @@
 	.show	= proc_key_users_show,
 };
 
-static struct file_operations proc_key_users_fops = {
+static const struct file_operations proc_key_users_fops = {
 	.open		= proc_key_users_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c8bf6e1..93b3177 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -161,7 +161,7 @@
 #define sel_write_enforce NULL
 #endif
 
-static struct file_operations sel_enforce_ops = {
+static const struct file_operations sel_enforce_ops = {
 	.read		= sel_read_enforce,
 	.write		= sel_write_enforce,
 };
@@ -211,7 +211,7 @@
 #define sel_write_disable NULL
 #endif
 
-static struct file_operations sel_disable_ops = {
+static const struct file_operations sel_disable_ops = {
 	.write		= sel_write_disable,
 };
 
@@ -225,7 +225,7 @@
 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
-static struct file_operations sel_policyvers_ops = {
+static const struct file_operations sel_policyvers_ops = {
 	.read		= sel_read_policyvers,
 };
 
@@ -242,7 +242,7 @@
 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
-static struct file_operations sel_mls_ops = {
+static const struct file_operations sel_mls_ops = {
 	.read		= sel_read_mls,
 };
 
@@ -294,7 +294,7 @@
 	return length;
 }
 
-static struct file_operations sel_load_ops = {
+static const struct file_operations sel_load_ops = {
 	.write		= sel_write_load,
 };
 
@@ -374,7 +374,7 @@
 	free_page((unsigned long) page);
 	return length;
 }
-static struct file_operations sel_checkreqprot_ops = {
+static const struct file_operations sel_checkreqprot_ops = {
 	.read		= sel_read_checkreqprot,
 	.write		= sel_write_checkreqprot,
 };
@@ -423,7 +423,7 @@
 	free_page((unsigned long) page);
 	return length;
 }
-static struct file_operations sel_compat_net_ops = {
+static const struct file_operations sel_compat_net_ops = {
 	.read		= sel_read_compat_net,
 	.write		= sel_write_compat_net,
 };
@@ -467,7 +467,7 @@
 	return rv;
 }
 
-static struct file_operations transaction_ops = {
+static const struct file_operations transaction_ops = {
 	.write		= selinux_transaction_write,
 	.read		= simple_transaction_read,
 	.release	= simple_transaction_release,
@@ -875,7 +875,7 @@
 	return length;
 }
 
-static struct file_operations sel_bool_ops = {
+static const struct file_operations sel_bool_ops = {
 	.read           = sel_read_bool,
 	.write          = sel_write_bool,
 };
@@ -932,7 +932,7 @@
 	return length;
 }
 
-static struct file_operations sel_commit_bools_ops = {
+static const struct file_operations sel_commit_bools_ops = {
 	.write          = sel_commit_bools_write,
 };
 
@@ -1131,12 +1131,12 @@
 	return ret;
 }
 
-static struct file_operations sel_avc_cache_threshold_ops = {
+static const struct file_operations sel_avc_cache_threshold_ops = {
 	.read		= sel_read_avc_cache_threshold,
 	.write		= sel_write_avc_cache_threshold,
 };
 
-static struct file_operations sel_avc_hash_stats_ops = {
+static const struct file_operations sel_avc_hash_stats_ops = {
 	.read		= sel_read_avc_hash_stats,
 };
 
@@ -1198,7 +1198,7 @@
 	return seq_open(file, &sel_avc_cache_stats_seq_ops);
 }
 
-static struct file_operations sel_avc_cache_stats_ops = {
+static const struct file_operations sel_avc_cache_stats_ops = {
 	.open		= sel_open_avc_cache_stats,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
diff --git a/sound/core/control.c b/sound/core/control.c
index 42bcf27..86de725 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1398,7 +1398,7 @@
  *  INIT PART
  */
 
-static struct file_operations snd_ctl_f_ops =
+static const struct file_operations snd_ctl_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_ctl_read,
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 39c03f3..96ffdf1 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -317,7 +317,7 @@
 
  */
 
-static struct file_operations snd_hwdep_f_ops =
+static const struct file_operations snd_hwdep_f_ops =
 {
 	.owner = 	THIS_MODULE,
 	.llseek =	snd_hwdep_llseek,
diff --git a/sound/core/info.c b/sound/core/info.c
index 54591e2..bf6dbf9 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -507,7 +507,7 @@
 	return -ENXIO;
 }
 
-static struct file_operations snd_info_entry_operations =
+static const struct file_operations snd_info_entry_operations =
 {
 	.owner =		THIS_MODULE,
 	.llseek =		snd_info_entry_llseek,
diff --git a/sound/core/init.c b/sound/core/init.c
index db61037..4a431e3 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -36,7 +36,7 @@
 static DEFINE_SPINLOCK(shutdown_lock);
 static LIST_HEAD(shutdown_files);
 
-static struct file_operations snd_shutdown_f_ops;
+static const struct file_operations snd_shutdown_f_ops;
 
 static unsigned int snd_cards_lock;	/* locked for registering/using */
 struct snd_card *snd_cards[SNDRV_CARDS];
@@ -244,7 +244,7 @@
 	return -ENODEV;
 }
 
-static struct file_operations snd_shutdown_f_ops =
+static const struct file_operations snd_shutdown_f_ops =
 {
 	.owner = 	THIS_MODULE,
 	.llseek =	snd_disconnect_llseek,
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 3391f2a..74a2923 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -390,7 +390,7 @@
  *  REGISTRATION PART
  */
 
-static struct file_operations snd_mixer_oss_f_ops =
+static const struct file_operations snd_mixer_oss_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.open =		snd_mixer_oss_open,
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 786a82e..c4744bb 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2889,7 +2889,7 @@
  *  ENTRY functions
  */
 
-static struct file_operations snd_pcm_oss_f_reg =
+static const struct file_operations snd_pcm_oss_f_reg =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_pcm_oss_read,
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index b52e893..3e276fc 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3424,7 +3424,7 @@
  *  Register section
  */
 
-struct file_operations snd_pcm_f_ops[2] = {
+const struct file_operations snd_pcm_f_ops[2] = {
 	{
 		.owner =		THIS_MODULE,
 		.write =		snd_pcm_write,
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 7e6ceec..d14dcbb 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1359,7 +1359,7 @@
  *  Register functions
  */
 
-static struct file_operations snd_rawmidi_f_ops =
+static const struct file_operations snd_rawmidi_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_rawmidi_read,
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 92858cf..2eb9873 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -208,7 +208,7 @@
  * registration of sequencer minor device
  */
 
-static struct file_operations seq_oss_f_ops =
+static const struct file_operations seq_oss_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		odev_read,
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index bb9dd9f..694efe8 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -2538,7 +2538,7 @@
  *  REGISTRATION PART
  */
 
-static struct file_operations snd_seq_f_ops =
+static const struct file_operations snd_seq_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_seq_read,
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 4084de0..70600df 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -168,7 +168,7 @@
 	return err;
 }
 
-static struct file_operations snd_fops =
+static const struct file_operations snd_fops =
 {
 	.owner =	THIS_MODULE,
 	.open =		snd_open
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 3e06383..160e40e 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1901,7 +1901,7 @@
 #define snd_timer_user_ioctl_compat	NULL
 #endif
 
-static struct file_operations snd_timer_f_ops =
+static const struct file_operations snd_timer_f_ops =
 {
 	.owner =	THIS_MODULE,
 	.read =		snd_timer_user_read,
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index 09263d7..f072432 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -778,7 +778,7 @@
 	return 0;
 }
 
-static struct file_operations ad1889_fops = {
+static const struct file_operations ad1889_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= ad1889_read,
@@ -812,7 +812,7 @@
 	return codec->mixer_ioctl(codec, cmd, arg);
 }
 
-static struct file_operations ad1889_mixer_fops = {
+static const struct file_operations ad1889_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.ioctl		= ad1889_mixer_ioctl,
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index 2197951..a339f0c 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -1354,11 +1354,11 @@
 		((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
 
 #ifdef DEBUG
-	for (count=0; count<sizeof(ioctl_str)/sizeof(ioctl_str[0]); count++) {
+	for (count = 0; count < ARRAY_SIZE(ioctl_str); count++) {
 		if (ioctl_str[count].cmd == cmd)
 			break;
 	}
-	if (count < sizeof(ioctl_str) / sizeof(ioctl_str[0]))
+	if (count < ARRAY_SIZE(ioctl_str))
 		pr_debug("ioctl %s, arg=0x%lxn", ioctl_str[count].str, arg);
 	else
 		pr_debug("ioctl 0x%x unknown, arg=0x%lx\n", cmd, arg);
diff --git a/sound/oss/btaudio.c b/sound/oss/btaudio.c
index ad7210a..f845528 100644
--- a/sound/oss/btaudio.c
+++ b/sound/oss/btaudio.c
@@ -429,7 +429,7 @@
 	return 0;
 }
 
-static struct file_operations btaudio_mixer_fops = {
+static const struct file_operations btaudio_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.open		= btaudio_mixer_open,
@@ -796,7 +796,7 @@
 	return mask;
 }
 
-static struct file_operations btaudio_digital_dsp_fops = {
+static const struct file_operations btaudio_digital_dsp_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.open		= btaudio_dsp_open_digital,
@@ -807,7 +807,7 @@
 	.poll		= btaudio_dsp_poll,
 };
 
-static struct file_operations btaudio_analog_dsp_fops = {
+static const struct file_operations btaudio_analog_dsp_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.open		= btaudio_dsp_open_analog,
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index 80b836e..a0ec886 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -371,7 +371,7 @@
 	return -EINVAL;
 }
 
-static struct file_operations mixer_fops =
+static const struct file_operations mixer_fops =
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
@@ -1337,7 +1337,7 @@
 	return -EINVAL;
 }
 
-static struct file_operations sq_fops =
+static const struct file_operations sq_fops =
 {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
@@ -1561,7 +1561,7 @@
 	return n;
 }
 
-static struct file_operations state_fops = {
+static const struct file_operations state_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= state_read,
diff --git a/sound/oss/emu10k1/audio.c b/sound/oss/emu10k1/audio.c
index efcf589..e75ea21 100644
--- a/sound/oss/emu10k1/audio.c
+++ b/sound/oss/emu10k1/audio.c
@@ -1582,7 +1582,7 @@
 	return;
 }
 
-struct file_operations emu10k1_audio_fops = {
+const struct file_operations emu10k1_audio_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= emu10k1_audio_read,
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index cca3dad..df1e990 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -458,7 +458,7 @@
 }
 
 /* MIDI file operations */
-struct file_operations emu10k1_midi_fops = {
+const struct file_operations emu10k1_midi_fops = {
 	.owner		= THIS_MODULE,
 	.read		= emu10k1_midi_read,
 	.write		= emu10k1_midi_write,
diff --git a/sound/oss/emu10k1/mixer.c b/sound/oss/emu10k1/mixer.c
index 6419796..bc3805f 100644
--- a/sound/oss/emu10k1/mixer.c
+++ b/sound/oss/emu10k1/mixer.c
@@ -681,7 +681,7 @@
 	return 0;
 }
 
-struct file_operations emu10k1_mixer_fops = {
+const struct file_operations emu10k1_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.ioctl		= emu10k1_mixer_ioctl,
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
index cc282a0..e1fbcca 100644
--- a/sound/oss/es1371.c
+++ b/sound/oss/es1371.c
@@ -131,6 +131,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
+#include <linux/kernel.h>
 
 #include <asm/io.h>
 #include <asm/page.h>
@@ -2998,7 +2999,7 @@
 	set_fs(KERNEL_DS);
 	val = SOUND_MASK_LINE;
 	mixdev_ioctl(s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-	for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(initvol); i++) {
 		val = initvol[i].vol;
 		mixdev_ioctl(s->codec, initvol[i].mixch, (unsigned long)&val);
 	}
diff --git a/sound/oss/hal2.c b/sound/oss/hal2.c
index d18286c..80a4277 100644
--- a/sound/oss/hal2.c
+++ b/sound/oss/hal2.c
@@ -1377,7 +1377,7 @@
 	return 0;
 }
 
-static struct file_operations hal2_audio_fops = {
+static const struct file_operations hal2_audio_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= hal2_read,
@@ -1388,7 +1388,7 @@
 	.release	= hal2_release,
 };
 
-static struct file_operations hal2_mixer_fops = {
+static const struct file_operations hal2_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.ioctl		= hal2_ioctl_mixdev,
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index 24110d6..f1f49eb 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -1106,7 +1106,7 @@
 	return IRQ_HANDLED;
 }
 
-static struct file_operations dev_fileops = {
+static const struct file_operations dev_fileops = {
 	.owner		= THIS_MODULE,
 	.read		= dev_read,
 	.write		= dev_write,
diff --git a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c
index da9728e..d459bdb 100644
--- a/sound/oss/nec_vrc5477.c
+++ b/sound/oss/nec_vrc5477.c
@@ -1381,11 +1381,11 @@
 	int val, ret;
 
 #ifdef VRC5477_AC97_DEBUG
-	for (count=0; count<sizeof(ioctl_str)/sizeof(ioctl_str[0]); count++) {
+	for (count = 0; count < ARRAY_SIZE(ioctl_str); count++) {
 		if (ioctl_str[count].cmd == cmd)
 			break;
 	}
-	if (count < sizeof(ioctl_str)/sizeof(ioctl_str[0]))
+	if (count < ARRAY_SIZE(ioctl_str))
 		printk(KERN_INFO PFX "ioctl %s\n", ioctl_str[count].str);
 	else
 		printk(KERN_INFO PFX "ioctl unknown, 0x%x\n", cmd);
diff --git a/sound/oss/os.h b/sound/oss/os.h
index 0490562..a1a962d 100644
--- a/sound/oss/os.h
+++ b/sound/oss/os.h
@@ -43,4 +43,4 @@
 #undef PSEUDO_DMA_AUTOINIT
 #define ALLOW_BUFFER_MAPPING
 
-extern struct file_operations oss_sound_fops;
+extern const struct file_operations oss_sound_fops;
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
index 51f5541..7ea9acc 100644
--- a/sound/oss/sh_dac_audio.c
+++ b/sound/oss/sh_dac_audio.c
@@ -255,7 +255,7 @@
 	return 0;
 }
 
-struct file_operations dac_audio_fops = {
+const struct file_operations dac_audio_fops = {
       .read =		dac_audio_read,
       .write =	dac_audio_write,
       .ioctl =	dac_audio_ioctl,
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index a89108c..dcd8d6d 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -32,6 +32,7 @@
 #include <linux/ctype.h>
 #include <linux/stddef.h>
 #include <linux/kmod.h>
+#include <linux/kernel.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <linux/wait.h>
@@ -482,7 +483,7 @@
 	return 0;
 }
 
-struct file_operations oss_sound_fops = {
+const struct file_operations oss_sound_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.read		= sound_read,
@@ -557,7 +558,7 @@
 	/* Protecting the innocent */
 	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
-	for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
+	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 		device_create(sound_class, NULL,
 			      MKDEV(SOUND_MAJOR, dev_list[i].minor),
 			      "%s", dev_list[i].name);
@@ -581,7 +582,7 @@
 {
 	int i, j;
 
-	for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
+	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 		device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
 		if (!dev_list[i].num)
 			continue;
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
index 471c274..9f7e5f5 100644
--- a/sound/oss/swarm_cs4297a.c
+++ b/sound/oss/swarm_cs4297a.c
@@ -77,6 +77,7 @@
 #include <linux/poll.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
+#include <linux/kernel.h>
 
 #include <asm/byteorder.h>
 #include <asm/dma.h>
@@ -2676,7 +2677,7 @@
 #if 0
                 val = SOUND_MASK_LINE;
                 mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val);
-                for (i = 0; i < sizeof(initvol) / sizeof(initvol[0]); i++) {
+                for (i = 0; i < ARRAY_SIZE(initvol); i++) {
                         val = initvol[i].vol;
                         mixer_ioctl(s, initvol[i].mixch, (unsigned long) &val);
                 }
diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
index c96cc8c..7ab3a73 100644
--- a/sound/oss/via82cxxx_audio.c
+++ b/sound/oss/via82cxxx_audio.c
@@ -1619,7 +1619,7 @@
 }
 
 
-static struct file_operations via_mixer_fops = {
+static const struct file_operations via_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.open		= via_mixer_open,
 	.llseek		= no_llseek,
@@ -2042,7 +2042,7 @@
  *
  */
 
-static struct file_operations via_dsp_fops = {
+static const struct file_operations via_dsp_fops = {
 	.owner		= THIS_MODULE,
 	.open		= via_dsp_open,
 	.release	= via_dsp_release,
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
index 6dfb9f4..d25249a 100644
--- a/sound/oss/vwsnd.c
+++ b/sound/oss/vwsnd.c
@@ -3035,7 +3035,7 @@
 	return err;
 }
 
-static struct file_operations vwsnd_audio_fops = {
+static const struct file_operations vwsnd_audio_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.read =		vwsnd_audio_read,
@@ -3225,7 +3225,7 @@
 	return retval;
 }
 
-static struct file_operations vwsnd_mixer_fops = {
+static const struct file_operations vwsnd_mixer_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.ioctl =	vwsnd_mixer_ioctl,
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 8f1ced4..46daca1 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -436,7 +436,7 @@
 
 static int soundcore_open(struct inode *, struct file *);
 
-static struct file_operations soundcore_fops=
+static const struct file_operations soundcore_fops=
 {
 	/* We must have an owner or the module locking fails */
 	.owner	= THIS_MODULE,