Merge branch 'x86/core' into x86/mce2
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index ceddcff..e638e15 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -1,3 +1,46 @@
+What:		/sys/bus/pci/drivers/.../bind
+Date:		December 2003
+Contact:	linux-pci@vger.kernel.org
+Description:
+		Writing a device location to this file will cause
+		the driver to attempt to bind to the device found at
+		this location.	This is useful for overriding default
+		bindings.  The format for the location is: DDDD:BB:DD.F.
+		That is Domain:Bus:Device.Function and is the same as
+		found in /sys/bus/pci/devices/.  For example:
+		# echo 0000:00:19.0 > /sys/bus/pci/drivers/foo/bind
+		(Note: kernels before 2.6.28 may require echo -n).
+
+What:		/sys/bus/pci/drivers/.../unbind
+Date:		December 2003
+Contact:	linux-pci@vger.kernel.org
+Description:
+		Writing a device location to this file will cause the
+		driver to attempt to unbind from the device found at
+		this location.	This may be useful when overriding default
+		bindings.  The format for the location is: DDDD:BB:DD.F.
+		That is Domain:Bus:Device.Function and is the same as
+		found in /sys/bus/pci/devices/. For example:
+		# echo 0000:00:19.0 > /sys/bus/pci/drivers/foo/unbind
+		(Note: kernels before 2.6.28 may require echo -n).
+
+What:		/sys/bus/pci/drivers/.../new_id
+Date:		December 2003
+Contact:	linux-pci@vger.kernel.org
+Description:
+		Writing a device ID to this file will attempt to
+		dynamically add a new device ID to a PCI device driver.
+		This may allow the driver to support more hardware than
+		was included in the driver's static device ID support
+		table at compile time.  The format for the device ID is:
+		VVVV DDDD SVVV SDDD CCCC MMMM PPPP.  That is Vendor ID,
+		Device ID, Subsystem Vendor ID, Subsystem Device ID,
+		Class, Class Mask, and Private Driver Data.  The Vendor ID
+		and Device ID fields are required, the rest are optional.
+		Upon successfully adding an ID, the driver will probe
+		for the device and attempt to bind to it.  For example:
+		# echo "8086 10f5" > /sys/bus/pci/drivers/foo/new_id
+
 What:		/sys/bus/pci/devices/.../vpd
 Date:		February 2008
 Contact:	Ben Hutchings <bhutchings@solarflare.com>
diff --git a/Documentation/dvb/README.flexcop b/Documentation/dvb/README.flexcop
deleted file mode 100644
index 5515469..0000000
--- a/Documentation/dvb/README.flexcop
+++ /dev/null
@@ -1,205 +0,0 @@
-This README escorted the skystar2-driver rewriting procedure. It describes the
-state of the new flexcop-driver set and some internals are written down here
-too.
-
-This document hopefully describes things about the flexcop and its
-device-offsprings. Goal was to write an easy-to-write and easy-to-read set of
-drivers based on the skystar2.c and other information.
-
-Remark: flexcop-pci.c was a copy of skystar2.c, but every line has been
-touched and rewritten.
-
-History & News
-==============
-  2005-04-01 - correct USB ISOC transfers (thanks to Vadim Catana)
-
-
-
-
-General coding processing
-=========================
-
-We should proceed as follows (as long as no one complains):
-
-0) Think before start writing code!
-
-1) rewriting the skystar2.c with the help of the flexcop register descriptions
-and splitting up the files to a pci-bus-part and a flexcop-part.
-The new driver will be called b2c2-flexcop-pci.ko/b2c2-flexcop-usb.ko for the
-device-specific part and b2c2-flexcop.ko for the common flexcop-functions.
-
-2) Search for errors in the leftover of flexcop-pci.c (compare with pluto2.c
-and other pci drivers)
-
-3) make some beautification (see 'Improvements when rewriting (refactoring) is
-done')
-
-4) Testing the new driver and maybe substitute the skystar2.c with it, to reach
-a wider tester audience.
-
-5) creating an usb-bus-part using the already written flexcop code for the pci
-card.
-
-Idea: create a kernel-object for the flexcop and export all important
-functions. This option saves kernel-memory, but maybe a lot of functions have
-to be exported to kernel namespace.
-
-
-Current situation
-=================
-
-0) Done :)
-1) Done (some minor issues left)
-2) Done
-3) Not ready yet, more information is necessary
-4) next to be done (see the table below)
-5) USB driver is working (yes, there are some minor issues)
-
-What seems to be ready?
------------------------
-
-1) Rewriting
-1a) i2c is cut off from the flexcop-pci.c and seems to work
-1b) moved tuner and demod stuff from flexcop-pci.c to flexcop-tuner-fe.c
-1c) moved lnb and diseqc stuff from flexcop-pci.c to flexcop-tuner-fe.c
-1e) eeprom (reading MAC address)
-1d) sram (no dynamic sll size detection (commented out) (using default as JJ told me))
-1f) misc. register accesses for reading parameters (e.g. resetting, revision)
-1g) pid/mac filter (flexcop-hw-filter.c)
-1i) dvb-stuff initialization in flexcop.c (done)
-1h) dma stuff (now just using the size-irq, instead of all-together, to be done)
-1j) remove flexcop initialization from flexcop-pci.c completely (done)
-1l) use a well working dma IRQ method (done, see 'Known bugs and problems and TODO')
-1k) cleanup flexcop-files (remove unused EXPORT_SYMBOLs, make static from
-non-static where possible, moved code to proper places)
-
-2) Search for errors in the leftover of flexcop-pci.c (partially done)
-5a) add MAC address reading
-5c) feeding of ISOC data to the software demux (format of the isochronous data
-and speed optimization, no real error) (thanks to Vadim Catana)
-
-What to do in the near future?
---------------------------------------
-(no special order here)
-
-5) USB driver
-5b) optimize isoc-transfer (submitting/killing isoc URBs when transfer is starting)
-
-Testing changes
----------------
-
-O             = item is working
-P             = item is partially working
-X             = item is not working
-N             = item does not apply here
-<empty field> = item need to be examined
-
-       | PCI                               | USB
-item   | mt352 | nxt2002 | stv0299 | mt312 | mt352 | nxt2002 | stv0299 | mt312
--------+-------+---------+---------+-------+-------+---------+---------+-------
-1a)    | O     |         |         |       | N     | N       | N       | N
-1b)    | O     |         |         |       |       |         | O       |
-1c)    | N     | N       |         |       | N     | N       | O       |
-1d)    |                 O                 |                 O
-1e)    |                 O                 |                 O
-1f)    |                                   P
-1g)    |                                   O
-1h)    |                 P                 |
-1i)    |                 O                 |                 N
-1j)    |                 O                 |                 N
-1l)    |                 O                 |                 N
-2)     |                 O                 |                 N
-5a)    |                 N                 |                 O
-5b)*   |                 N                 |
-5c)    |                 N                 |                 O
-
-* - not done yet
-
-Known bugs and problems and TODO
---------------------------------
-
-1g/h/l) when pid filtering is enabled on the pci card
-
-DMA usage currently:
-  The DMA is splitted in 2 equal-sized subbuffers. The Flexcop writes to first
-  address and triggers an IRQ when it's full and starts writing to the second
-  address. When the second address is full, the IRQ is triggered again, and
-  the flexcop writes to first address again, and so on.
-  The buffersize of each address is currently 640*188 bytes.
-
-  Problem is, when using hw-pid-filtering and doing some low-bandwidth
-  operation (like scanning) the buffers won't be filled enough to trigger
-  the IRQ. That's why:
-
-  When PID filtering is activated, the timer IRQ is used. Every 1.97 ms the IRQ
-  is triggered.  Is the current write address of DMA1 different to the one
-  during the last IRQ, then the data is passed to the demuxer.
-
-  There is an additional DMA-IRQ-method: packet count IRQ. This isn't
-  implemented correctly yet.
-
-  The solution is to disable HW PID filtering, but I don't know how the DVB
-  API software demux behaves on slow systems with 45MBit/s TS.
-
-Solved bugs :)
---------------
-1g) pid-filtering (somehow pid index 4 and 5 (EMM_PID and ECM_PID) aren't
-working)
-SOLUTION: also index 0 was affected, because net_translation is done for
-these indexes by default
-
-5b) isochronous transfer does only work in the first attempt (for the Sky2PC
-USB, Air2PC is working) SOLUTION: the flexcop was going asleep and never really
-woke up again (don't know if this need fixes, see
-flexcop-fe-tuner.c:flexcop_sleep)
-
-NEWS: when the driver is loaded and unloaded and loaded again (w/o doing
-anything in the while the driver is loaded the first time), no transfers take
-place anymore.
-
-Improvements when rewriting (refactoring) is done
-=================================================
-
-- split sleeping of the flexcop (misc_204.ACPI3_sig = 1;) from lnb_control
-  (enable sleeping for other demods than dvb-s)
-- add support for CableStar (stv0297 Microtune 203x/ALPS) (almost done, incompatibilities with the Nexus-CA)
-
-Debugging
----------
-- add verbose debugging to skystar2.c (dump the reg_dw_data) and compare it
-  with this flexcop, this is important, because i2c is now using the
-  flexcop_ibi_value union from flexcop-reg.h (do you have a better idea for
-  that, please tell us so).
-
-Everything which is identical in the following table, can be put into a common
-flexcop-module.
-
-		  PCI                  USB
--------------------------------------------------------------------------------
-Different:
-Register access:  accessing IO memory  USB control message
-I2C bus:          I2C bus of the FC    USB control message
-Data transfer:    DMA                  isochronous transfer
-EEPROM transfer:  through i2c bus      not clear yet
-
-Identical:
-Streaming:                 accessing registers
-PID Filtering:             accessing registers
-Sram destinations:         accessing registers
-Tuner/Demod:                     I2C bus
-DVB-stuff:            can be written for common use
-
-Acknowledgements (just for the rewriting part)
-================
-
-Bjarne Steinsbo thought a lot in the first place of the pci part for this code
-sharing idea.
-
-Andreas Oberritter for providing a recent PCI initialization template
-(pluto2.c).
-
-Boleslaw Ciesielski for pointing out a problem with firmware loader.
-
-Vadim Catana for correcting the USB transfer.
-
-comments, critics and ideas to linux-dvb@linuxtv.org.
diff --git a/Documentation/dvb/technisat.txt b/Documentation/dvb/technisat.txt
index cdf6ee4..3f435ff 100644
--- a/Documentation/dvb/technisat.txt
+++ b/Documentation/dvb/technisat.txt
@@ -1,5 +1,5 @@
-How to set up the Technisat devices
-===================================
+How to set up the Technisat/B2C2 Flexcop devices
+================================================
 
 1) Find out what device you have
 ================================
@@ -16,54 +16,60 @@
 
 If the Technisat is the only TV device in your box get rid of unnecessary modules and check this one:
 "Multimedia devices" => "Customise analog and hybrid tuner modules to build"
-In this directory uncheck every driver which is activated there.
+In this directory uncheck every driver which is activated there (except "Simple tuner support" for case 9 only).
 
 Then please activate:
 2a) Main module part:
 
 a.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters"
-b.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC PCI" in case of a PCI card OR
+b.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC PCI" in case of a PCI card
+OR
 c.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC USB" in case of an USB 1.1 adapter
 d.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Enable debug for the B2C2 FlexCop drivers"
 Notice: d.) is helpful for troubleshooting
 
 2b) Frontend module part:
 
-1.) Revision 2.3:
+1.) SkyStar DVB-S Revision 2.3:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Zarlink VP310/MT312/ZL10313 based"
 
-2.) Revision 2.6:
+2.) SkyStar DVB-S Revision 2.6:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "ST STV0299 based"
 
-3.) Revision 2.7:
+3.) SkyStar DVB-S Revision 2.7:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Samsung S5H1420 based"
 c.)"Multimedia devices" => "Customise DVB frontends" => "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
 d.)"Multimedia devices" => "Customise DVB frontends" => "ISL6421 SEC controller"
 
-4.) Revision 2.8:
+4.) SkyStar DVB-S Revision 2.8:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Conexant CX24113/CX24128 tuner for DVB-S/DSS"
 c.)"Multimedia devices" => "Customise DVB frontends" => "Conexant CX24123 based"
 d.)"Multimedia devices" => "Customise DVB frontends" => "ISL6421 SEC controller"
 
-5.) DVB-T card:
+5.) AirStar DVB-T card:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Zarlink MT352 based"
 
-6.) DVB-C card:
+6.) CableStar DVB-C card:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "ST STV0297 based"
 
-7.) ATSC card 1st generation:
+7.) AirStar ATSC card 1st generation:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "Broadcom BCM3510"
 
-8.) ATSC card 2nd generation:
+8.) AirStar ATSC card 2nd generation:
 a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
 b.)"Multimedia devices" => "Customise DVB frontends" => "NxtWave Communications NXT2002/NXT2004 based"
-c.)"Multimedia devices" => "Customise DVB frontends" => "LG Electronics LGDT3302/LGDT3303 based"
+c.)"Multimedia devices" => "Customise DVB frontends" => "Generic I2C PLL based tuners"
 
-Author: Uwe Bugla <uwe.bugla@gmx.de> December 2008
+9.) AirStar ATSC card 3rd generation:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "LG Electronics LGDT3302/LGDT3303 based"
+c.)"Multimedia devices" => "Customise analog and hybrid tuner modules to build" => "Simple tuner support"
+
+Author: Uwe Bugla <uwe.bugla@gmx.de> February 2009
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f6d5d5b..28de395 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -868,8 +868,10 @@
 	icn=		[HW,ISDN]
 			Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
 
-	ide=		[HW] (E)IDE subsystem
-			Format: ide=nodma or ide=doubler
+	ide-core.nodma=	[HW] (E)IDE subsystem
+			Format: =0.0 to prevent dma on hda, =0.1 hdb =1.0 hdc
+			.vlb_clock .pci_clock .noflush .noprobe .nowerr .cdrom
+			.chs .ignore_cable are additional options
 			See Documentation/ide/ide.txt.
 
 	idebus=		[HW] (E)IDE subsystem - VLB/PCI bus speed
@@ -1308,8 +1310,13 @@
 
 	memtest=	[KNL,X86] Enable memtest
 			Format: <integer>
-			range: 0,4 : pattern number
 			default : 0 <disable>
+			Specifies the number of memtest passes to be
+			performed. Each pass selects another test
+			pattern from a given set of patterns. Memtest
+			fills the memory with this pattern, validates
+			memory contents and reserves bad memory
+			regions that are detected.
 
 	meye.*=		[HW] Set MotionEye Camera parameters
 			See Documentation/video4linux/meye.txt.
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c
index a957d23..38b6a9c 100644
--- a/arch/arm/mach-davinci/board-evm.c
+++ b/arch/arm/mach-davinci/board-evm.c
@@ -311,6 +311,9 @@
 	gpio_request(gpio + 7, "nCF_SEL");
 	gpio_direction_output(gpio + 7, 1);
 
+	/* irlml6401 sustains over 3A, switches 5V in under 8 msec */
+	setup_usb(500, 8);
+
 	return 0;
 }
 
@@ -417,9 +420,6 @@
 	platform_add_devices(davinci_evm_devices,
 			     ARRAY_SIZE(davinci_evm_devices));
 	evm_init_i2c();
-
-	/* irlml6401 sustains over 3A, switches 5V in under 8 msec */
-	setup_usb(500, 8);
 }
 
 static __init void davinci_evm_irq_init(void)
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 28f6dbc..abb92b7 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -231,6 +231,11 @@
 		.lpsc = DAVINCI_LPSC_GPIO,
 	},
 	{
+		.name = "usb",
+		.rate = &commonrate,
+		.lpsc = DAVINCI_LPSC_USB,
+	},
+	{
 		.name = "AEMIFCLK",
 		.rate = &commonrate,
 		.lpsc = DAVINCI_LPSC_AEMIF,
diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
index 867ead2..6968078 100644
--- a/arch/arm/mach-davinci/usb.c
+++ b/arch/arm/mach-davinci/usb.c
@@ -47,6 +47,7 @@
 #elif defined(CONFIG_USB_MUSB_HOST)
 	.mode           = MUSB_HOST,
 #endif
+	.clock		= "usb",
 	.config		= &musb_config,
 };
 
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index e88d417..c7fc01e 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -19,6 +19,7 @@
 #include <linux/serial_8250.h>
 #include <linux/ata_platform.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
 
 #include <asm/elf.h>
 #include <asm/mach-types.h>
@@ -201,8 +202,13 @@
 	&pata_device,
 };
 
+static struct i2c_board_info i2c_rtc = {
+	I2C_BOARD_INFO("pcf8583", 0x50)
+};
+
 static int __init rpc_init(void)
 {
+	i2c_register_board_info(0, &i2c_rtc, 1);
 	return platform_add_devices(devs, ARRAY_SIZE(devs));
 }
 
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 4eb45c0..153e727 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -638,6 +638,17 @@
 	  and include PCI device scope covered by these DMA
 	  remapping devices.
 
+config DMAR_DEFAULT_ON
+	def_bool y
+	prompt "Enable DMA Remapping Devices by default"
+	depends on DMAR
+	help
+	  Selecting this option will enable a DMAR device at boot time if
+	  one is found. If this option is not selected, DMAR support can
+	  be enabled by passing intel_iommu=on to the kernel. It is
+	  recommended you say N here while the DMAR code remains
+	  experimental.
+
 endmenu
 
 endif
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 006ad36..166e0d8 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -507,7 +507,7 @@
 	if (trigger == IOSAPIC_EDGE)
 		return -EINVAL;
 
-	for (i = 0; i <= NR_IRQS; i++) {
+	for (i = 0; i < NR_IRQS; i++) {
 		info = &iosapic_intr_info[i];
 		if (info->trigger == trigger && info->polarity == pol &&
 		    (info->dmode == IOSAPIC_FIXED ||
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index 67810b7..b6c0e63 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -2149,7 +2149,7 @@
 
 	/* next, remove hash table entries for this table */
 
-	for (index = 0; index <= UNW_HASH_SIZE; ++index) {
+	for (index = 0; index < UNW_HASH_SIZE; ++index) {
 		tmp = unw.cache + unw.hash[index];
 		if (unw.hash[index] >= UNW_CACHE_SIZE
 		    || tmp->ip < table->start || tmp->ip >= table->end)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 600eef3..e61465a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -603,7 +603,7 @@
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
-	select CPU_CAVIUM_OCTEON
+	select SYS_HAS_CPU_CAVIUM_OCTEON
 	help
 	  The Octeon simulator is software performance model of the Cavium
 	  Octeon Processor. It supports simulating Octeon processors on x86
@@ -618,7 +618,7 @@
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_HAS_EARLY_PRINTK
-	select CPU_CAVIUM_OCTEON
+	select SYS_HAS_CPU_CAVIUM_OCTEON
 	select SWAP_IO_SPACE
 	help
 	  This option supports all of the Octeon reference boards from Cavium
@@ -1234,6 +1234,7 @@
 
 config CPU_CAVIUM_OCTEON
 	bool "Cavium Octeon processor"
+	depends on SYS_HAS_CPU_CAVIUM_OCTEON
 	select IRQ_CPU
 	select IRQ_CPU_OCTEON
 	select CPU_HAS_PREFETCH
@@ -1314,6 +1315,9 @@
 config SYS_HAS_CPU_SB1
 	bool
 
+config SYS_HAS_CPU_CAVIUM_OCTEON
+	bool
+
 #
 # CPU may reorder R->R, R->W, W->R, W->W
 # Reordering beyond LL and SC is handled in WEAK_REORDERING_BEYOND_LLSC
@@ -1387,6 +1391,7 @@
 config 64BIT
 	bool "64-bit kernel"
 	depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
+	select HAVE_SYSCALL_WRAPPERS
 	help
 	  Select this option if you want to build a 64-bit kernel.
 
diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c
index 6fd441d..f58d4ff 100644
--- a/arch/mips/alchemy/common/time.c
+++ b/arch/mips/alchemy/common/time.c
@@ -118,7 +118,7 @@
 	 * setup counter 1 (RTC) to tick at full speed
 	 */
 	t = 0xffffff;
-	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && t--)
+	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && --t)
 		asm volatile ("nop");
 	if (!t)
 		goto cntr_err;
@@ -127,7 +127,7 @@
 	au_sync();
 
 	t = 0xffffff;
-	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && t--)
+	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
 		asm volatile ("nop");
 	if (!t)
 		goto cntr_err;
@@ -135,7 +135,7 @@
 	au_sync();
 
 	t = 0xffffff;
-	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && t--)
+	while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && --t)
 		asm volatile ("nop");
 	if (!t)
 		goto cntr_err;
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index a0ff2b6..4b4007b 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -111,7 +111,6 @@
 			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].chip->name);
-		seq_printf(p, "-%-8s", irq_desc[i].name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index aa2c55e..2f8452b 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/binfmts.h>
 #include <linux/security.h>
+#include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <linux/vfs.h>
 #include <linux/ipc.h>
@@ -63,9 +64,9 @@
 #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
 #endif
 
-asmlinkage unsigned long
-sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-         unsigned long flags, unsigned long fd, unsigned long pgoff)
+SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len,
+	unsigned long, prot, unsigned long, flags, unsigned long, fd,
+	unsigned long, pgoff)
 {
 	struct file * file = NULL;
 	unsigned long error;
@@ -121,21 +122,21 @@
 	int	rlim_max;
 };
 
-asmlinkage long sys32_truncate64(const char __user * path,
-	unsigned long __dummy, int a2, int a3)
+SYSCALL_DEFINE4(32_truncate64, const char __user *, path,
+	unsigned long, __dummy, unsigned long, a2, unsigned long, a3)
 {
 	return sys_truncate(path, merge_64(a2, a3));
 }
 
-asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
-	int a2, int a3)
+SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy,
+	unsigned long, a2, unsigned long, a3)
 {
 	return sys_ftruncate(fd, merge_64(a2, a3));
 }
 
-asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
-			    unsigned int offset_low, loff_t __user * result,
-			    unsigned int origin)
+SYSCALL_DEFINE5(32_llseek, unsigned long, fd, unsigned long, offset_high,
+	unsigned long, offset_low, loff_t __user *, result,
+	unsigned long, origin)
 {
 	return sys_llseek(fd, offset_high, offset_low, result, origin);
 }
@@ -144,20 +145,20 @@
    lseek back to original location.  They fail just like lseek does on
    non-seekable files.  */
 
-asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf,
-			       size_t count, u32 unused, u64 a4, u64 a5)
+SYSCALL_DEFINE6(32_pread, unsigned long, fd, char __user *, buf, size_t, count,
+	unsigned long, unused, unsigned long, a4, unsigned long, a5)
 {
 	return sys_pread64(fd, buf, count, merge_64(a4, a5));
 }
 
-asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf,
-			        size_t count, u32 unused, u64 a4, u64 a5)
+SYSCALL_DEFINE6(32_pwrite, unsigned int, fd, const char __user *, buf,
+	size_t, count, u32, unused, u64, a4, u64, a5)
 {
 	return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
 }
 
-asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
-	struct compat_timespec __user *interval)
+SYSCALL_DEFINE2(32_sched_rr_get_interval, compat_pid_t, pid,
+	struct compat_timespec __user *, interval)
 {
 	struct timespec t;
 	int ret;
@@ -174,8 +175,8 @@
 
 #ifdef CONFIG_SYSVIPC
 
-asmlinkage long
-sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third,
+	unsigned long, ptr, unsigned long, fifth)
 {
 	int version, err;
 
@@ -233,8 +234,8 @@
 
 #else
 
-asmlinkage long
-sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+SYSCALL_DEFINE6(32_ipc, u32, call, int, first, int, second, int, third,
+	u32, ptr, u32 fifth)
 {
 	return -ENOSYS;
 }
@@ -242,7 +243,7 @@
 #endif /* CONFIG_SYSVIPC */
 
 #ifdef CONFIG_MIPS32_N32
-asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg)
+SYSCALL_DEFINE4(n32_semctl, int, semid, int, semnum, int, cmd, u32, arg)
 {
 	/* compat_sys_semctl expects a pointer to union semun */
 	u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
@@ -251,13 +252,14 @@
 	return compat_sys_semctl(semid, semnum, cmd, uptr);
 }
 
-asmlinkage long sysn32_msgsnd(int msqid, u32 msgp, unsigned msgsz, int msgflg)
+SYSCALL_DEFINE4(n32_msgsnd, int, msqid, u32, msgp, unsigned int, msgsz,
+	int, msgflg)
 {
 	return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp));
 }
 
-asmlinkage long sysn32_msgrcv(int msqid, u32 msgp, size_t msgsz, int msgtyp,
-			      int msgflg)
+SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
+	int, msgtyp, int, msgflg)
 {
 	return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64,
 				 compat_ptr(msgp));
@@ -277,7 +279,7 @@
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 
-asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
+SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
 {
 	struct sysctl_args32 tmp;
 	int error;
@@ -316,9 +318,16 @@
 	return error;
 }
 
+#else
+
+SYSCALL_DEFINE1(32_sysctl, struct sysctl_args32 __user *, args)
+{
+	return -ENOSYS;
+}
+
 #endif /* CONFIG_SYSCTL_SYSCALL */
 
-asmlinkage long sys32_newuname(struct new_utsname __user * name)
+SYSCALL_DEFINE1(32_newuname, struct new_utsname __user *, name)
 {
 	int ret = 0;
 
@@ -334,7 +343,7 @@
 	return ret;
 }
 
-asmlinkage int sys32_personality(unsigned long personality)
+SYSCALL_DEFINE1(32_personality, unsigned long, personality)
 {
 	int ret;
 	personality &= 0xffffffff;
@@ -357,7 +366,7 @@
 
 extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf);
 
-asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32)
+SYSCALL_DEFINE2(32_ustat, dev_t, dev, struct ustat32 __user *, ubuf32)
 {
 	int err;
 	struct ustat tmp;
@@ -381,8 +390,8 @@
 	return err;
 }
 
-asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
-	s32 count)
+SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd,
+	compat_off_t __user *, offset, s32, count)
 {
 	mm_segment_t old_fs = get_fs();
 	int ret;
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 51d1ba4..9ab70c3 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -399,7 +399,7 @@
 	sys	sys_swapon		2
 	sys	sys_reboot		3
 	sys	sys_old_readdir		3
-	sys	old_mmap		6	/* 4090 */
+	sys	sys_mips_mmap		6	/* 4090 */
 	sys	sys_munmap		2
 	sys	sys_truncate		2
 	sys	sys_ftruncate		2
@@ -519,7 +519,7 @@
 	sys	sys_sendfile		4
 	sys	sys_ni_syscall		0
 	sys	sys_ni_syscall		0
-	sys	sys_mmap2		6	/* 4210 */
+	sys	sys_mips_mmap2		6	/* 4210 */
 	sys	sys_truncate64		4
 	sys	sys_ftruncate64		4
 	sys	sys_stat64		2
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index a9e1716..9b46986 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -207,7 +207,7 @@
 	PTR	sys_newlstat
 	PTR	sys_poll
 	PTR	sys_lseek
-	PTR	old_mmap
+	PTR	sys_mips_mmap
 	PTR	sys_mprotect			/* 5010 */
 	PTR	sys_munmap
 	PTR	sys_brk
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 30f3b63..7438e92 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -129,12 +129,12 @@
 	PTR	sys_newlstat
 	PTR	sys_poll
 	PTR	sys_lseek
-	PTR	old_mmap
+	PTR	sys_mips_mmap
 	PTR	sys_mprotect			/* 6010 */
 	PTR	sys_munmap
 	PTR	sys_brk
-	PTR	sys32_rt_sigaction
-	PTR	sys32_rt_sigprocmask
+	PTR	sys_32_rt_sigaction
+	PTR	sys_32_rt_sigprocmask
 	PTR	compat_sys_ioctl		/* 6015 */
 	PTR	sys_pread64
 	PTR	sys_pwrite64
@@ -159,7 +159,7 @@
 	PTR	compat_sys_setitimer
 	PTR	sys_alarm
 	PTR	sys_getpid
-	PTR	sys32_sendfile
+	PTR	sys_32_sendfile
 	PTR	sys_socket			/* 6040 */
 	PTR	sys_connect
 	PTR	sys_accept
@@ -181,14 +181,14 @@
 	PTR	sys_exit
 	PTR	compat_sys_wait4
 	PTR	sys_kill			/* 6060 */
-	PTR	sys32_newuname
+	PTR	sys_32_newuname
 	PTR	sys_semget
 	PTR	sys_semop
-	PTR	sysn32_semctl
+	PTR	sys_n32_semctl
 	PTR	sys_shmdt			/* 6065 */
 	PTR	sys_msgget
-	PTR	sysn32_msgsnd
-	PTR	sysn32_msgrcv
+	PTR	sys_n32_msgsnd
+	PTR	sys_n32_msgrcv
 	PTR	compat_sys_msgctl
 	PTR	compat_sys_fcntl		/* 6070 */
 	PTR	sys_flock
@@ -245,15 +245,15 @@
 	PTR	sys_getsid
 	PTR	sys_capget
 	PTR	sys_capset
-	PTR	sys32_rt_sigpending		/* 6125 */
+	PTR	sys_32_rt_sigpending		/* 6125 */
 	PTR	compat_sys_rt_sigtimedwait
-	PTR	sys32_rt_sigqueueinfo
+	PTR	sys_32_rt_sigqueueinfo
 	PTR	sysn32_rt_sigsuspend
 	PTR	sys32_sigaltstack
 	PTR	compat_sys_utime		/* 6130 */
 	PTR	sys_mknod
-	PTR	sys32_personality
-	PTR	sys32_ustat
+	PTR	sys_32_personality
+	PTR	sys_32_ustat
 	PTR	compat_sys_statfs
 	PTR	compat_sys_fstatfs		/* 6135 */
 	PTR	sys_sysfs
@@ -265,14 +265,14 @@
 	PTR	sys_sched_getscheduler
 	PTR	sys_sched_get_priority_max
 	PTR	sys_sched_get_priority_min
-	PTR	sys32_sched_rr_get_interval	/* 6145 */
+	PTR	sys_32_sched_rr_get_interval	/* 6145 */
 	PTR	sys_mlock
 	PTR	sys_munlock
 	PTR	sys_mlockall
 	PTR	sys_munlockall
 	PTR	sys_vhangup			/* 6150 */
 	PTR	sys_pivot_root
-	PTR	sys32_sysctl
+	PTR	sys_32_sysctl
 	PTR	sys_prctl
 	PTR	compat_sys_adjtimex
 	PTR	compat_sys_setrlimit		/* 6155 */
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index fefef4a..b0fef4f 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -265,12 +265,12 @@
 	PTR	sys_olduname
 	PTR	sys_umask			/* 4060 */
 	PTR	sys_chroot
-	PTR	sys32_ustat
+	PTR	sys_32_ustat
 	PTR	sys_dup2
 	PTR	sys_getppid
 	PTR	sys_getpgrp			/* 4065 */
 	PTR	sys_setsid
-	PTR	sys32_sigaction
+	PTR	sys_32_sigaction
 	PTR	sys_sgetmask
 	PTR	sys_ssetmask
 	PTR	sys_setreuid			/* 4070 */
@@ -293,7 +293,7 @@
 	PTR	sys_swapon
 	PTR	sys_reboot
 	PTR	compat_sys_old_readdir
-	PTR	old_mmap			/* 4090 */
+	PTR	sys_mips_mmap			/* 4090 */
 	PTR	sys_munmap
 	PTR	sys_truncate
 	PTR	sys_ftruncate
@@ -320,12 +320,12 @@
 	PTR	compat_sys_wait4
 	PTR	sys_swapoff			/* 4115 */
 	PTR	compat_sys_sysinfo
-	PTR	sys32_ipc
+	PTR	sys_32_ipc
 	PTR	sys_fsync
 	PTR	sys32_sigreturn
 	PTR	sys32_clone			/* 4120 */
 	PTR	sys_setdomainname
-	PTR	sys32_newuname
+	PTR	sys_32_newuname
 	PTR	sys_ni_syscall			/* sys_modify_ldt */
 	PTR	compat_sys_adjtimex
 	PTR	sys_mprotect			/* 4125 */
@@ -339,11 +339,11 @@
 	PTR	sys_fchdir
 	PTR	sys_bdflush
 	PTR	sys_sysfs			/* 4135 */
-	PTR	sys32_personality
+	PTR	sys_32_personality
 	PTR	sys_ni_syscall	 		/* for afs_syscall */
 	PTR	sys_setfsuid
 	PTR	sys_setfsgid
-	PTR	sys32_llseek			/* 4140 */
+	PTR	sys_32_llseek			/* 4140 */
 	PTR	compat_sys_getdents
 	PTR	compat_sys_select
 	PTR	sys_flock
@@ -356,7 +356,7 @@
 	PTR	sys_ni_syscall			/* 4150 */
 	PTR	sys_getsid
 	PTR	sys_fdatasync
-	PTR	sys32_sysctl
+	PTR	sys_32_sysctl
 	PTR	sys_mlock
 	PTR	sys_munlock			/* 4155 */
 	PTR	sys_mlockall
@@ -368,7 +368,7 @@
 	PTR	sys_sched_yield
 	PTR	sys_sched_get_priority_max
 	PTR	sys_sched_get_priority_min
-	PTR	sys32_sched_rr_get_interval 	/* 4165 */
+	PTR	sys_32_sched_rr_get_interval 	/* 4165 */
 	PTR	compat_sys_nanosleep
 	PTR	sys_mremap
 	PTR	sys_accept
@@ -397,25 +397,25 @@
 	PTR	sys_getresgid
 	PTR	sys_prctl
 	PTR	sys32_rt_sigreturn
-	PTR	sys32_rt_sigaction
-	PTR	sys32_rt_sigprocmask 		/* 4195 */
-	PTR	sys32_rt_sigpending
+	PTR	sys_32_rt_sigaction
+	PTR	sys_32_rt_sigprocmask 		/* 4195 */
+	PTR	sys_32_rt_sigpending
 	PTR	compat_sys_rt_sigtimedwait
-	PTR	sys32_rt_sigqueueinfo
+	PTR	sys_32_rt_sigqueueinfo
 	PTR	sys32_rt_sigsuspend
-	PTR	sys32_pread			/* 4200 */
-	PTR	sys32_pwrite
+	PTR	sys_32_pread			/* 4200 */
+	PTR	sys_32_pwrite
 	PTR	sys_chown
 	PTR	sys_getcwd
 	PTR	sys_capget
 	PTR	sys_capset			/* 4205 */
 	PTR	sys32_sigaltstack
-	PTR	sys32_sendfile
+	PTR	sys_32_sendfile
 	PTR	sys_ni_syscall
 	PTR	sys_ni_syscall
-	PTR	sys32_mmap2			/* 4210 */
-	PTR	sys32_truncate64
-	PTR	sys32_ftruncate64
+	PTR	sys_mips_mmap2			/* 4210 */
+	PTR	sys_32_truncate64
+	PTR	sys_32_ftruncate64
 	PTR	sys_newstat
 	PTR	sys_newlstat
 	PTR	sys_newfstat			/* 4215 */
@@ -481,7 +481,7 @@
 	PTR	compat_sys_mq_notify		/* 4275 */
 	PTR	compat_sys_mq_getsetattr
 	PTR	sys_ni_syscall			/* sys_vserver */
-	PTR	sys32_waitid
+	PTR	sys_32_waitid
 	PTR	sys_ni_syscall			/* available, was setaltroot */
 	PTR	sys_add_key			/* 4280 */
 	PTR	sys_request_key
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index a4e106c..830c5ef 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -19,6 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/compiler.h>
+#include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
 #include <asm/abi.h>
@@ -338,8 +339,8 @@
 }
 
 #ifdef CONFIG_TRAD_SIGNALS
-asmlinkage int sys_sigaction(int sig, const struct sigaction __user *act,
-	struct sigaction __user *oact)
+SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act,
+	struct sigaction __user *, oact)
 {
 	struct k_sigaction new_ka, old_ka;
 	int ret;
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 652709b..2e74075 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -349,8 +349,8 @@
 	return -ERESTARTNOHAND;
 }
 
-asmlinkage int sys32_sigaction(int sig, const struct sigaction32 __user *act,
-                               struct sigaction32 __user *oact)
+SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
+	struct sigaction32 __user *, oact)
 {
 	struct k_sigaction new_ka, old_ka;
 	int ret;
@@ -704,9 +704,9 @@
 	.restart	= __NR_O32_restart_syscall
 };
 
-asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
-				  struct sigaction32 __user *oact,
-				  unsigned int sigsetsize)
+SYSCALL_DEFINE4(32_rt_sigaction, int, sig,
+	const struct sigaction32 __user *, act,
+	struct sigaction32 __user *, oact, unsigned int, sigsetsize)
 {
 	struct k_sigaction new_sa, old_sa;
 	int ret = -EINVAL;
@@ -748,8 +748,8 @@
 	return ret;
 }
 
-asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
-	compat_sigset_t __user *oset, unsigned int sigsetsize)
+SYSCALL_DEFINE4(32_rt_sigprocmask, int, how, compat_sigset_t __user *, set,
+	compat_sigset_t __user *, oset, unsigned int, sigsetsize)
 {
 	sigset_t old_set, new_set;
 	int ret;
@@ -770,8 +770,8 @@
 	return ret;
 }
 
-asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
-	unsigned int sigsetsize)
+SYSCALL_DEFINE2(32_rt_sigpending, compat_sigset_t __user *, uset,
+	unsigned int, sigsetsize)
 {
 	int ret;
 	sigset_t set;
@@ -787,7 +787,8 @@
 	return ret;
 }
 
-asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
+SYSCALL_DEFINE3(32_rt_sigqueueinfo, int, pid, int, sig,
+	compat_siginfo_t __user *, uinfo)
 {
 	siginfo_t info;
 	int ret;
@@ -802,10 +803,9 @@
 	return ret;
 }
 
-asmlinkage long
-sys32_waitid(int which, compat_pid_t pid,
-	     compat_siginfo_t __user *uinfo, int options,
-	     struct compat_rusage __user *uru)
+SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
+	     compat_siginfo_t __user *, uinfo, int, options,
+	     struct compat_rusage __user *, uru)
 {
 	siginfo_t info;
 	struct rusage ru;
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 37970d9..8cf3846 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -152,9 +152,9 @@
 	return error;
 }
 
-asmlinkage unsigned long
-old_mmap(unsigned long addr, unsigned long len, int prot,
-	int flags, int fd, off_t offset)
+SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
+	unsigned long, prot, unsigned long, flags, unsigned long,
+	fd, off_t, offset)
 {
 	unsigned long result;
 
@@ -168,9 +168,9 @@
 	return result;
 }
 
-asmlinkage unsigned long
-sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
-          unsigned long flags, unsigned long fd, unsigned long pgoff)
+SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
+	unsigned long, prot, unsigned long, flags, unsigned long, fd,
+	unsigned long, pgoff)
 {
 	if (pgoff & (~PAGE_MASK >> 12))
 		return -EINVAL;
@@ -240,7 +240,7 @@
 /*
  * Compacrapability ...
  */
-asmlinkage int sys_uname(struct old_utsname __user * name)
+SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
 {
 	if (name && !copy_to_user(name, utsname(), sizeof (*name)))
 		return 0;
@@ -250,7 +250,7 @@
 /*
  * Compacrapability ...
  */
-asmlinkage int sys_olduname(struct oldold_utsname __user * name)
+SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
 {
 	int error;
 
@@ -279,7 +279,7 @@
 	return error;
 }
 
-asmlinkage int sys_set_thread_area(unsigned long addr)
+SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
 {
 	struct thread_info *ti = task_thread_info(current);
 
@@ -290,7 +290,7 @@
 	return 0;
 }
 
-asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
+asmlinkage int _sys_sysmips(long cmd, long arg1, long arg2, long arg3)
 {
 	switch (cmd) {
 	case MIPS_ATOMIC_SET:
@@ -325,8 +325,8 @@
  *
  * This is really horribly ugly.
  */
-asmlinkage int sys_ipc(unsigned int call, int first, int second,
-		       unsigned long third, void __user *ptr, long fifth)
+SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, second,
+	unsigned long, third, void __user *, ptr, long, fifth)
 {
 	int version, ret;
 
@@ -411,7 +411,7 @@
 /*
  * No implemented yet ...
  */
-asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
+SYSCALL_DEFINE3(cachectl, char *, addr, int, nbytes, int, op)
 {
 	return -ENOSYS;
 }
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 98ad0a8..694d51f 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -13,6 +13,7 @@
 #include <linux/linkage.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/syscalls.h>
 #include <linux/mm.h>
 
 #include <asm/cacheflush.h>
@@ -58,8 +59,8 @@
  * We could optimize the case where the cache argument is not BCACHE but
  * that seems very atypical use ...
  */
-asmlinkage int sys_cacheflush(unsigned long addr,
-	unsigned long bytes, unsigned int cache)
+SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes,
+	unsigned int, cache)
 {
 	if (bytes == 0)
 		return 0;
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index ada0692..73cb6a3 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -367,27 +367,24 @@
 static int emulate_fp_pair(unsigned char __user *addr, unsigned int reg,
 			   unsigned int flags)
 {
-	char *ptr = (char *) &current->thread.TS_FPR(reg);
-	int i, ret;
+	char *ptr0 = (char *) &current->thread.TS_FPR(reg);
+	char *ptr1 = (char *) &current->thread.TS_FPR(reg+1);
+	int i, ret, sw = 0;
 
 	if (!(flags & F))
 		return 0;
 	if (reg & 1)
 		return 0;	/* invalid form: FRS/FRT must be even */
-	if (!(flags & SW)) {
-		/* not byte-swapped - easy */
-		if (!(flags & ST))
-			ret = __copy_from_user(ptr, addr, 16);
-		else
-			ret = __copy_to_user(addr, ptr, 16);
-	} else {
-		/* each FPR value is byte-swapped separately */
-		ret = 0;
-		for (i = 0; i < 16; ++i) {
-			if (!(flags & ST))
-				ret |= __get_user(ptr[i^7], addr + i);
-			else
-				ret |= __put_user(ptr[i^7], addr + i);
+	if (flags & SW)
+		sw = 7;
+	ret = 0;
+	for (i = 0; i < 8; ++i) {
+		if (!(flags & ST)) {
+			ret |= __get_user(ptr0[i^sw], addr + i);
+			ret |= __get_user(ptr1[i^sw], addr + i + 8);
+		} else {
+			ret |= __put_user(ptr0[i^sw], addr + i);
+			ret |= __put_user(ptr1[i^sw], addr + i + 8);
 		}
 	}
 	if (ret)
diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S
index 70693a5..693b14a 100644
--- a/arch/powerpc/lib/copyuser_64.S
+++ b/arch/powerpc/lib/copyuser_64.S
@@ -62,18 +62,19 @@
 72:	std	r8,8(r3)
 	beq+	3f
 	addi	r3,r3,16
-23:	ld	r9,8(r4)
 .Ldo_tail:
 	bf	cr7*4+1,1f
-	rotldi	r9,r9,32
+23:	lwz	r9,8(r4)
+	addi	r4,r4,4
 73:	stw	r9,0(r3)
 	addi	r3,r3,4
 1:	bf	cr7*4+2,2f
-	rotldi	r9,r9,16
+44:	lhz	r9,8(r4)
+	addi	r4,r4,2
 74:	sth	r9,0(r3)
 	addi	r3,r3,2
 2:	bf	cr7*4+3,3f
-	rotldi	r9,r9,8
+45:	lbz	r9,8(r4)
 75:	stb	r9,0(r3)
 3:	li	r3,0
 	blr
@@ -141,11 +142,24 @@
 6:	cmpwi	cr1,r5,8
 	addi	r3,r3,32
 	sld	r9,r9,r10
-	ble	cr1,.Ldo_tail
+	ble	cr1,7f
 34:	ld	r0,8(r4)
 	srd	r7,r0,r11
 	or	r9,r7,r9
-	b	.Ldo_tail
+7:
+	bf	cr7*4+1,1f
+	rotldi	r9,r9,32
+94:	stw	r9,0(r3)
+	addi	r3,r3,4
+1:	bf	cr7*4+2,2f
+	rotldi	r9,r9,16
+95:	sth	r9,0(r3)
+	addi	r3,r3,2
+2:	bf	cr7*4+3,3f
+	rotldi	r9,r9,8
+96:	stb	r9,0(r3)
+3:	li	r3,0
+	blr
 
 .Ldst_unaligned:
 	PPC_MTOCRF	0x01,r6		/* put #bytes to 8B bdry into cr7 */
@@ -218,7 +232,6 @@
 121:
 132:
 	addi	r3,r3,8
-123:
 134:
 135:
 138:
@@ -226,6 +239,9 @@
 140:
 141:
 142:
+123:
+144:
+145:
 
 /*
  * here we have had a fault on a load and r3 points to the first
@@ -309,6 +325,9 @@
 187:
 188:
 189:	
+194:
+195:
+196:
 1:
 	ld	r6,-24(r1)
 	ld	r5,-8(r1)
@@ -329,7 +348,9 @@
 	.llong	72b,172b
 	.llong	23b,123b
 	.llong	73b,173b
+	.llong	44b,144b
 	.llong	74b,174b
+	.llong	45b,145b
 	.llong	75b,175b
 	.llong	24b,124b
 	.llong	25b,125b
@@ -347,6 +368,9 @@
 	.llong	79b,179b
 	.llong	80b,180b
 	.llong	34b,134b
+	.llong	94b,194b
+	.llong	95b,195b
+	.llong	96b,196b
 	.llong	35b,135b
 	.llong	81b,181b
 	.llong	36b,136b
diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S
index fe2d34e..e178922 100644
--- a/arch/powerpc/lib/memcpy_64.S
+++ b/arch/powerpc/lib/memcpy_64.S
@@ -53,18 +53,19 @@
 3:	std	r8,8(r3)
 	beq	3f
 	addi	r3,r3,16
-	ld	r9,8(r4)
 .Ldo_tail:
 	bf	cr7*4+1,1f
-	rotldi	r9,r9,32
+	lwz	r9,8(r4)
+	addi	r4,r4,4
 	stw	r9,0(r3)
 	addi	r3,r3,4
 1:	bf	cr7*4+2,2f
-	rotldi	r9,r9,16
+	lhz	r9,8(r4)
+	addi	r4,r4,2
 	sth	r9,0(r3)
 	addi	r3,r3,2
 2:	bf	cr7*4+3,3f
-	rotldi	r9,r9,8
+	lbz	r9,8(r4)
 	stb	r9,0(r3)
 3:	ld	r3,48(r1)	/* return dest pointer */
 	blr
@@ -133,11 +134,24 @@
 	cmpwi	cr1,r5,8
 	addi	r3,r3,32
 	sld	r9,r9,r10
-	ble	cr1,.Ldo_tail
+	ble	cr1,6f
 	ld	r0,8(r4)
 	srd	r7,r0,r11
 	or	r9,r7,r9
-	b	.Ldo_tail
+6:
+	bf	cr7*4+1,1f
+	rotldi	r9,r9,32
+	stw	r9,0(r3)
+	addi	r3,r3,4
+1:	bf	cr7*4+2,2f
+	rotldi	r9,r9,16
+	sth	r9,0(r3)
+	addi	r3,r3,2
+2:	bf	cr7*4+3,3f
+	rotldi	r9,r9,8
+	stb	r9,0(r3)
+3:	ld	r3,48(r1)	/* return dest pointer */
+	blr
 
 .Ldst_unaligned:
 	PPC_MTOCRF	0x01,r6		# put #bytes to 8B bdry into cr7
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 77fae5f..5558d93 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -204,6 +204,23 @@
 {
 	u32 ma, pcila, pciha;
 
+	/* Hack warning ! The "old" PCI 2.x cell only let us configure the low
+	 * 32-bit of incoming PLB addresses. The top 4 bits of the 36-bit
+	 * address are actually hard wired to a value that appears to depend
+	 * on the specific SoC. For example, it's 0 on 440EP and 1 on 440EPx.
+	 *
+	 * The trick here is we just crop those top bits and ignore them when
+	 * programming the chip. That means the device-tree has to be right
+	 * for the specific part used (we don't print a warning if it's wrong
+	 * but on the other hand, you'll crash quickly enough), but at least
+	 * this code should work whatever the hard coded value is
+	 */
+	plb_addr &= 0xffffffffull;
+
+	/* Note: Due to the above hack, the test below doesn't actually test
+	 * if you address is above 4G, but it tests that address and
+	 * (address + size) are both contained in the same 4G
+	 */
 	if ((plb_addr + size) > 0xffffffffull || !is_power_of_2(size) ||
 	    size < 0x1000 || (plb_addr & (size - 1)) != 0) {
 		printk(KERN_WARNING "%s: Resource out of range\n",
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
index 7c35787..72da416 100644
--- a/arch/sh/boards/board-ap325rxa.c
+++ b/arch/sh/boards/board-ap325rxa.c
@@ -22,7 +22,6 @@
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_gpio.h>
-#include <media/ov772x.h>
 #include <media/soc_camera_platform.h>
 #include <media/sh_mobile_ceu.h>
 #include <video/sh_mobile_lcdc.h>
@@ -224,7 +223,6 @@
 }
 
 #ifdef CONFIG_I2C
-/* support for the old ncm03j camera */
 static unsigned char camera_ncm03j_magic[] =
 {
 	0x87, 0x00, 0x88, 0x08, 0x89, 0x01, 0x8A, 0xE8,
@@ -245,23 +243,6 @@
 	0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
 };
 
-static int camera_probe(void)
-{
-	struct i2c_adapter *a = i2c_get_adapter(0);
-	struct i2c_msg msg;
-	int ret;
-
-	camera_power(1);
-	msg.addr = 0x6e;
-	msg.buf = camera_ncm03j_magic;
-	msg.len = 2;
-	msg.flags = 0;
-	ret = i2c_transfer(a, &msg, 1);
-	camera_power(0);
-
-	return ret;
-}
-
 static int camera_set_capture(struct soc_camera_platform_info *info,
 			      int enable)
 {
@@ -313,35 +294,8 @@
 		.platform_data	= &camera_info,
 	},
 };
-
-static int __init camera_setup(void)
-{
-	if (camera_probe() > 0)
-		platform_device_register(&camera_device);
-
-	return 0;
-}
-late_initcall(camera_setup);
-
 #endif /* CONFIG_I2C */
 
-static int ov7725_power(struct device *dev, int mode)
-{
-	camera_power(0);
-	if (mode)
-		camera_power(1);
-
-	return 0;
-}
-
-static struct ov772x_camera_info ov7725_info = {
-	.buswidth  = SOCAM_DATAWIDTH_8,
-	.flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
-	.link = {
-		.power  = ov7725_power,
-	},
-};
-
 static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
 	.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
 	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
@@ -392,6 +346,9 @@
 	&ap325rxa_nor_flash_device,
 	&lcdc_device,
 	&ceu_device,
+#ifdef CONFIG_I2C
+	&camera_device,
+#endif
 	&nand_flash_device,
 	&sdcard_cn3_device,
 };
@@ -400,10 +357,6 @@
 	{
 		I2C_BOARD_INFO("pcf8563", 0x51),
 	},
-	{
-		I2C_BOARD_INFO("ov772x", 0x21),
-		.platform_data = &ov7725_info,
-	},
 };
 
 static struct spi_board_info ap325rxa_spi_devices[] = {
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
index 020a96f..4a5e597 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
@@ -18,8 +18,8 @@
 #include <asm/freq.h>
 #include <asm/io.h>
 
-const static int pll1rate[]={1,2,3,4,6,8};
-const static int pfc_divisors[]={1,2,3,4,6,8,12};
+static const int pll1rate[]={1,2,3,4,6,8};
+static const int pfc_divisors[]={1,2,3,4,6,8,12};
 #define ifc_divisors pfc_divisors
 
 #if (CONFIG_SH_CLK_MD == 0)
diff --git a/arch/sparc/kernel/chmc.c b/arch/sparc/kernel/chmc.c
index 3b9f4d6..e1a9598 100644
--- a/arch/sparc/kernel/chmc.c
+++ b/arch/sparc/kernel/chmc.c
@@ -306,6 +306,7 @@
 		buf[1] = '?';
 		buf[2] = '?';
 		buf[3] = '\0';
+		return 0;
 	}
 	p = dp->controller;
 	prop = &p->layout;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bd720a6..3afc94a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1827,7 +1827,7 @@
 	  remapping devices.
 
 config DMAR_DEFAULT_ON
-	def_bool n
+	def_bool y
 	prompt "Enable DMA Remapping Devices by default"
 	depends on DMAR
 	help
diff --git a/arch/x86/include/asm/iomap.h b/arch/x86/include/asm/iomap.h
index c1f0628..86af260 100644
--- a/arch/x86/include/asm/iomap.h
+++ b/arch/x86/include/asm/iomap.h
@@ -23,6 +23,9 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 
+int
+is_io_mapping_possible(resource_size_t base, unsigned long size);
+
 void *
 iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
 
diff --git a/arch/x86/include/asm/pat.h b/arch/x86/include/asm/pat.h
index 9709fdf..b0e7005 100644
--- a/arch/x86/include/asm/pat.h
+++ b/arch/x86/include/asm/pat.h
@@ -15,4 +15,7 @@
 		unsigned long req_type, unsigned long *ret_type);
 extern int free_memtype(u64 start, u64 end);
 
+extern int kernel_map_sync_memtype(u64 base, unsigned long size,
+		unsigned long flag);
+
 #endif /* _ASM_X86_PAT_H */
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 5e06259..a0ba613 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -157,7 +157,7 @@
 }
 
 static __always_inline unsigned long __copy_from_user_nocache(void *to,
-				const void __user *from, unsigned long n)
+		const void __user *from, unsigned long n, unsigned long total)
 {
 	might_fault();
 	if (__builtin_constant_p(n)) {
@@ -180,7 +180,7 @@
 
 static __always_inline unsigned long
 __copy_from_user_inatomic_nocache(void *to, const void __user *from,
-				  unsigned long n)
+				  unsigned long n, unsigned long total)
 {
        return __copy_from_user_ll_nocache_nozero(to, from, n);
 }
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index 987a2c1..dcaa0404 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -189,7 +189,7 @@
 				unsigned size, int zerorest);
 
 static inline int __copy_from_user_nocache(void *dst, const void __user *src,
-					   unsigned size)
+				   unsigned size, unsigned long total)
 {
 	might_sleep();
 	/*
@@ -198,17 +198,16 @@
 	 * non-temporal stores here. Smaller writes get handled
 	 * via regular __copy_from_user():
 	 */
-	if (likely(size >= PAGE_SIZE))
+	if (likely(total >= PAGE_SIZE))
 		return __copy_user_nocache(dst, src, size, 1);
 	else
 		return __copy_from_user(dst, src, size);
 }
 
 static inline int __copy_from_user_inatomic_nocache(void *dst,
-						    const void __user *src,
-						    unsigned size)
+	    const void __user *src, unsigned size, unsigned total)
 {
-	if (likely(size >= PAGE_SIZE))
+	if (likely(total >= PAGE_SIZE))
 		return __copy_user_nocache(dst, src, size, 0);
 	else
 		return __copy_from_user_inatomic(dst, src, size);
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 5b8394a..4c80f15 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -503,12 +503,12 @@
  */
 void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
 {
-	unsigned long flags;
 	char *vaddr;
 	int nr_pages = 2;
 	struct page *pages[2];
 	int i;
 
+	might_sleep();
 	if (!core_kernel_text((unsigned long)addr)) {
 		pages[0] = vmalloc_to_page(addr);
 		pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
@@ -522,9 +522,9 @@
 		nr_pages = 1;
 	vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
 	BUG_ON(!vaddr);
-	local_irq_save(flags);
+	local_irq_disable();
 	memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
-	local_irq_restore(flags);
+	local_irq_enable();
 	vunmap(vaddr);
 	sync_core();
 	/* Could also do a CLFLUSH here to speed up CPU recovery; but
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c
index cfe7b09..32838b5 100644
--- a/arch/x86/kernel/apic/summit_32.c
+++ b/arch/x86/kernel/apic/summit_32.c
@@ -48,7 +48,7 @@
 #include <linux/gfp.h>
 #include <linux/smp.h>
 
-static inline unsigned summit_get_apic_id(unsigned long x)
+static unsigned summit_get_apic_id(unsigned long x)
 {
 	return (x >> 24) & 0xFF;
 }
@@ -58,7 +58,7 @@
 	default_send_IPI_mask_sequence_logical(mask, vector);
 }
 
-static inline void summit_send_IPI_allbutself(int vector)
+static void summit_send_IPI_allbutself(int vector)
 {
 	cpumask_t mask = cpu_online_map;
 	cpu_clear(smp_processor_id(), mask);
@@ -67,7 +67,7 @@
 		summit_send_IPI_mask(&mask, vector);
 }
 
-static inline void summit_send_IPI_all(int vector)
+static void summit_send_IPI_all(int vector)
 {
 	summit_send_IPI_mask(&cpu_online_map, vector);
 }
@@ -82,8 +82,8 @@
 #define setup_summit()	{}
 #endif
 
-static inline int
-summit_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
+static int summit_mps_oem_check(struct mpc_table *mpc, char *oem,
+		char *productid)
 {
 	if (!strncmp(oem, "IBM ENSW", 8) &&
 			(!strncmp(productid, "VIGIL SMP", 9)
@@ -98,7 +98,7 @@
 }
 
 /* Hook from generic ACPI tables.c */
-static inline int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+static int summit_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
 	if (!strncmp(oem_id, "IBM", 3) &&
 	    (!strncmp(oem_table_id, "SERVIGIL", 8)
@@ -186,7 +186,7 @@
 
 #define SUMMIT_APIC_DFR_VALUE	(APIC_DFR_CLUSTER)
 
-static inline const cpumask_t *summit_target_cpus(void)
+static const cpumask_t *summit_target_cpus(void)
 {
 	/* CPU_MASK_ALL (0xff) has undefined behaviour with
 	 * dest_LowestPrio mode logical clustered apic interrupt routing
@@ -195,19 +195,18 @@
 	return &cpumask_of_cpu(0);
 }
 
-static inline unsigned long
-summit_check_apicid_used(physid_mask_t bitmap, int apicid)
+static unsigned long summit_check_apicid_used(physid_mask_t bitmap, int apicid)
 {
 	return 0;
 }
 
 /* we don't use the phys_cpu_present_map to indicate apicid presence */
-static inline unsigned long summit_check_apicid_present(int bit)
+static unsigned long summit_check_apicid_present(int bit)
 {
 	return 1;
 }
 
-static inline void summit_init_apic_ldr(void)
+static void summit_init_apic_ldr(void)
 {
 	unsigned long val, id;
 	int count = 0;
@@ -234,18 +233,18 @@
 	apic_write(APIC_LDR, val);
 }
 
-static inline int summit_apic_id_registered(void)
+static int summit_apic_id_registered(void)
 {
 	return 1;
 }
 
-static inline void summit_setup_apic_routing(void)
+static void summit_setup_apic_routing(void)
 {
 	printk("Enabling APIC mode:  Summit.  Using %d I/O APICs\n",
 						nr_ioapics);
 }
 
-static inline int summit_apicid_to_node(int logical_apicid)
+static int summit_apicid_to_node(int logical_apicid)
 {
 #ifdef CONFIG_SMP
 	return apicid_2_node[hard_smp_processor_id()];
@@ -266,7 +265,7 @@
 #endif
 }
 
-static inline int summit_cpu_present_to_apicid(int mps_cpu)
+static int summit_cpu_present_to_apicid(int mps_cpu)
 {
 	if (mps_cpu < nr_cpu_ids)
 		return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
@@ -274,28 +273,23 @@
 		return BAD_APICID;
 }
 
-static inline physid_mask_t
-summit_ioapic_phys_id_map(physid_mask_t phys_id_map)
+static physid_mask_t summit_ioapic_phys_id_map(physid_mask_t phys_id_map)
 {
 	/* For clustered we don't have a good way to do this yet - hack */
 	return physids_promote(0x0F);
 }
 
-static inline physid_mask_t summit_apicid_to_cpu_present(int apicid)
+static physid_mask_t summit_apicid_to_cpu_present(int apicid)
 {
 	return physid_mask_of_physid(0);
 }
 
-static inline void summit_setup_portio_remap(void)
-{
-}
-
-static inline int summit_check_phys_apicid_present(int boot_cpu_physical_apicid)
+static int summit_check_phys_apicid_present(int boot_cpu_physical_apicid)
 {
 	return 1;
 }
 
-static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask)
+static unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask)
 {
 	int cpus_found = 0;
 	int num_bits_set;
@@ -303,12 +297,10 @@
 	int cpu;
 
 	num_bits_set = cpus_weight(*cpumask);
-	/* Return id to all */
 	if (num_bits_set >= nr_cpu_ids)
-		return 0xFF;
+		return BAD_APICID;
 	/*
-	 * The cpus in the mask must all be on the apic cluster.  If are not
-	 * on the same apicid cluster return default value of target_cpus():
+	 * The cpus in the mask must all be on the apic cluster.
 	 */
 	cpu = first_cpu(*cpumask);
 	apicid = summit_cpu_to_logical_apicid(cpu);
@@ -318,9 +310,9 @@
 			int new_apicid = summit_cpu_to_logical_apicid(cpu);
 
 			if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
-				printk ("%s: Not a valid mask!\n", __func__);
+				printk("%s: Not a valid mask!\n", __func__);
 
-				return 0xFF;
+				return BAD_APICID;
 			}
 			apicid = apicid | new_apicid;
 			cpus_found++;
@@ -330,8 +322,7 @@
 	return apicid;
 }
 
-static inline unsigned int
-summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
+static unsigned int summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
 			      const struct cpumask *andmask)
 {
 	int apicid = summit_cpu_to_logical_apicid(0);
@@ -356,7 +347,7 @@
  *
  * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID.
  */
-static inline int summit_phys_pkg_id(int cpuid_apic, int index_msb)
+static int summit_phys_pkg_id(int cpuid_apic, int index_msb)
 {
 	return hard_smp_processor_id() >> index_msb;
 }
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index e858268..508bec1 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -858,6 +858,9 @@
  */
 void __init reserve_early(u64 start, u64 end, char *name)
 {
+	if (start >= end)
+		return;
+
 	drop_overlaps_that_are_ok(start, end);
 	__reserve_early(start, end, name, 0);
 }
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c
index ca53224..04102d4 100644
--- a/arch/x86/mm/iomap_32.c
+++ b/arch/x86/mm/iomap_32.c
@@ -20,6 +20,17 @@
 #include <asm/pat.h>
 #include <linux/module.h>
 
+int is_io_mapping_possible(resource_size_t base, unsigned long size)
+{
+#ifndef CONFIG_X86_PAE
+	/* There is no way to map greater than 1 << 32 address without PAE */
+	if (base + size > 0x100000000ULL)
+		return 0;
+#endif
+	return 1;
+}
+EXPORT_SYMBOL_GPL(is_io_mapping_possible);
+
 /* Map 'pfn' using fixed map 'type' and protections 'prot'
  */
 void *
diff --git a/arch/x86/mm/memtest.c b/arch/x86/mm/memtest.c
index 9cab18b..0bcd788 100644
--- a/arch/x86/mm/memtest.c
+++ b/arch/x86/mm/memtest.c
@@ -9,44 +9,44 @@
 
 #include <asm/e820.h>
 
-static void __init memtest(unsigned long start_phys, unsigned long size,
-				 unsigned pattern)
+static u64 patterns[] __initdata = {
+	0,
+	0xffffffffffffffffULL,
+	0x5555555555555555ULL,
+	0xaaaaaaaaaaaaaaaaULL,
+	0x1111111111111111ULL,
+	0x2222222222222222ULL,
+	0x4444444444444444ULL,
+	0x8888888888888888ULL,
+	0x3333333333333333ULL,
+	0x6666666666666666ULL,
+	0x9999999999999999ULL,
+	0xccccccccccccccccULL,
+	0x7777777777777777ULL,
+	0xbbbbbbbbbbbbbbbbULL,
+	0xddddddddddddddddULL,
+	0xeeeeeeeeeeeeeeeeULL,
+	0x7a6c7258554e494cULL, /* yeah ;-) */
+};
+
+static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad)
 {
-	unsigned long i;
-	unsigned long *start;
-	unsigned long start_bad;
-	unsigned long last_bad;
-	unsigned long val;
-	unsigned long start_phys_aligned;
-	unsigned long count;
-	unsigned long incr;
+	printk(KERN_INFO "  %016llx bad mem addr %010llx - %010llx reserved\n",
+	       (unsigned long long) pattern,
+	       (unsigned long long) start_bad,
+	       (unsigned long long) end_bad);
+	reserve_early(start_bad, end_bad, "BAD RAM");
+}
 
-	switch (pattern) {
-	case 0:
-		val = 0UL;
-		break;
-	case 1:
-		val = -1UL;
-		break;
-	case 2:
-#ifdef CONFIG_X86_64
-		val = 0x5555555555555555UL;
-#else
-		val = 0x55555555UL;
-#endif
-		break;
-	case 3:
-#ifdef CONFIG_X86_64
-		val = 0xaaaaaaaaaaaaaaaaUL;
-#else
-		val = 0xaaaaaaaaUL;
-#endif
-		break;
-	default:
-		return;
-	}
+static void __init memtest(u64 pattern, u64 start_phys, u64 size)
+{
+	u64 i, count;
+	u64 *start;
+	u64 start_bad, last_bad;
+	u64 start_phys_aligned;
+	size_t incr;
 
-	incr = sizeof(unsigned long);
+	incr = sizeof(pattern);
 	start_phys_aligned = ALIGN(start_phys, incr);
 	count = (size - (start_phys_aligned - start_phys))/incr;
 	start = __va(start_phys_aligned);
@@ -54,25 +54,42 @@
 	last_bad = 0;
 
 	for (i = 0; i < count; i++)
-		start[i] = val;
+		start[i] = pattern;
 	for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
-		if (*start != val) {
-			if (start_phys_aligned == last_bad + incr) {
-				last_bad += incr;
-			} else {
-				if (start_bad) {
-					printk(KERN_CONT "\n  %016lx bad mem addr %010lx - %010lx reserved",
-						val, start_bad, last_bad + incr);
-					reserve_early(start_bad, last_bad + incr, "BAD RAM");
-				}
-				start_bad = last_bad = start_phys_aligned;
-			}
+		if (*start == pattern)
+			continue;
+		if (start_phys_aligned == last_bad + incr) {
+			last_bad += incr;
+			continue;
 		}
+		if (start_bad)
+			reserve_bad_mem(pattern, start_bad, last_bad + incr);
+		start_bad = last_bad = start_phys_aligned;
 	}
-	if (start_bad) {
-		printk(KERN_CONT "\n  %016lx bad mem addr %010lx - %010lx reserved",
-			val, start_bad, last_bad + incr);
-		reserve_early(start_bad, last_bad + incr, "BAD RAM");
+	if (start_bad)
+		reserve_bad_mem(pattern, start_bad, last_bad + incr);
+}
+
+static void __init do_one_pass(u64 pattern, u64 start, u64 end)
+{
+	u64 size = 0;
+
+	while (start < end) {
+		start = find_e820_area_size(start, &size, 1);
+
+		/* done ? */
+		if (start >= end)
+			break;
+		if (start + size > end)
+			size = end - start;
+
+		printk(KERN_INFO "  %010llx - %010llx pattern %016llx\n",
+		       (unsigned long long) start,
+		       (unsigned long long) start + size,
+		       (unsigned long long) cpu_to_be64(pattern));
+		memtest(pattern, start, size);
+
+		start += size;
 	}
 }
 
@@ -90,33 +107,22 @@
 
 void __init early_memtest(unsigned long start, unsigned long end)
 {
-	u64 t_start, t_size;
-	unsigned pattern;
+	unsigned int i;
+	unsigned int idx = 0;
 
 	if (!memtest_pattern)
 		return;
 
-	printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern);
-	for (pattern = 0; pattern < memtest_pattern; pattern++) {
-		t_start = start;
-		t_size = 0;
-		while (t_start < end) {
-			t_start = find_e820_area_size(t_start, &t_size, 1);
-
-			/* done ? */
-			if (t_start >= end)
-				break;
-			if (t_start + t_size > end)
-				t_size = end - t_start;
-
-			printk(KERN_CONT "\n  %010llx - %010llx pattern %d",
-				(unsigned long long)t_start,
-				(unsigned long long)t_start + t_size, pattern);
-
-			memtest(t_start, t_size, pattern);
-
-			t_start += t_size;
-		}
+	printk(KERN_INFO "early_memtest: # of tests: %d\n", memtest_pattern);
+	for (i = 0; i < memtest_pattern; i++) {
+		idx = i % ARRAY_SIZE(patterns);
+		do_one_pass(patterns[idx], start, end);
 	}
-	printk(KERN_CONT "\n");
+
+	if (idx > 0) {
+		printk(KERN_INFO "early_memtest: wipe out "
+		       "test pattern from memory\n");
+		/* additional test with pattern 0 will do this */
+		do_one_pass(0, start, end);
+	}
 }
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 05f9aef..2ed3715 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -11,6 +11,7 @@
 #include <linux/bootmem.h>
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
@@ -634,6 +635,33 @@
 }
 
 /*
+ * Change the memory type for the physial address range in kernel identity
+ * mapping space if that range is a part of identity map.
+ */
+int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags)
+{
+	unsigned long id_sz;
+
+	if (!pat_enabled || base >= __pa(high_memory))
+		return 0;
+
+	id_sz = (__pa(high_memory) < base + size) ?
+				__pa(high_memory) - base :
+				size;
+
+	if (ioremap_change_attr((unsigned long)__va(base), id_sz, flags) < 0) {
+		printk(KERN_INFO
+			"%s:%d ioremap_change_attr failed %s "
+			"for %Lx-%Lx\n",
+			current->comm, current->pid,
+			cattr_name(flags),
+			base, (unsigned long long)(base + size));
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
  * Internal interface to reserve a range of physical memory with prot.
  * Reserved non RAM regions only and after successful reserve_memtype,
  * this func also keeps identity mapping (if any) in sync with this new prot.
@@ -642,7 +670,7 @@
 				int strict_prot)
 {
 	int is_ram = 0;
-	int id_sz, ret;
+	int ret;
 	unsigned long flags;
 	unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
 
@@ -679,23 +707,8 @@
 				     flags);
 	}
 
-	/* Need to keep identity mapping in sync */
-	if (paddr >= __pa(high_memory))
-		return 0;
-
-	id_sz = (__pa(high_memory) < paddr + size) ?
-				__pa(high_memory) - paddr :
-				size;
-
-	if (ioremap_change_attr((unsigned long)__va(paddr), id_sz, flags) < 0) {
+	if (kernel_map_sync_memtype(paddr, size, flags) < 0) {
 		free_memtype(paddr, paddr + size);
-		printk(KERN_ERR
-			"%s:%d reserve_pfn_range ioremap_change_attr failed %s "
-			"for %Lx-%Lx\n",
-			current->comm, current->pid,
-			cattr_name(flags),
-			(unsigned long long)paddr,
-			(unsigned long long)(paddr + size));
 		return -EINVAL;
 	}
 	return 0;
@@ -877,6 +890,7 @@
 	else
 		return pgprot_noncached(prot);
 }
+EXPORT_SYMBOL_GPL(pgprot_writecombine);
 
 #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT)
 
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 86497d5..c52f403 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -940,6 +940,9 @@
 	   possible map and a non-dummy shared_info. */
 	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
 
+	local_irq_disable();
+	early_boot_irqs_off();
+
 	xen_raw_console_write("mapping kernel into physical memory\n");
 	pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
 
diff --git a/block/blk-merge.c b/block/blk-merge.c
index b92f5b0..a104593 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -38,72 +38,84 @@
 	}
 }
 
-void blk_recalc_rq_segments(struct request *rq)
+static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
+					     struct bio *bio,
+					     unsigned int *seg_size_ptr)
 {
-	int nr_phys_segs;
 	unsigned int phys_size;
 	struct bio_vec *bv, *bvprv = NULL;
-	int seg_size;
-	int cluster;
-	struct req_iterator iter;
-	int high, highprv = 1;
-	struct request_queue *q = rq->q;
+	int cluster, i, high, highprv = 1;
+	unsigned int seg_size, nr_phys_segs;
+	struct bio *fbio;
 
-	if (!rq->bio)
-		return;
+	if (!bio)
+		return 0;
 
+	fbio = bio;
 	cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
 	seg_size = 0;
 	phys_size = nr_phys_segs = 0;
-	rq_for_each_segment(bv, rq, iter) {
-		/*
-		 * the trick here is making sure that a high page is never
-		 * considered part of another segment, since that might
-		 * change with the bounce page.
-		 */
-		high = page_to_pfn(bv->bv_page) > q->bounce_pfn;
-		if (high || highprv)
-			goto new_segment;
-		if (cluster) {
-			if (seg_size + bv->bv_len > q->max_segment_size)
+	for_each_bio(bio) {
+		bio_for_each_segment(bv, bio, i) {
+			/*
+			 * the trick here is making sure that a high page is
+			 * never considered part of another segment, since that
+			 * might change with the bounce page.
+			 */
+			high = page_to_pfn(bv->bv_page) > q->bounce_pfn;
+			if (high || highprv)
 				goto new_segment;
-			if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv))
-				goto new_segment;
-			if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv))
-				goto new_segment;
+			if (cluster) {
+				if (seg_size + bv->bv_len > q->max_segment_size)
+					goto new_segment;
+				if (!BIOVEC_PHYS_MERGEABLE(bvprv, bv))
+					goto new_segment;
+				if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv))
+					goto new_segment;
 
-			seg_size += bv->bv_len;
-			bvprv = bv;
-			continue;
-		}
+				seg_size += bv->bv_len;
+				bvprv = bv;
+				continue;
+			}
 new_segment:
-		if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size)
-			rq->bio->bi_seg_front_size = seg_size;
+			if (nr_phys_segs == 1 && seg_size >
+			    fbio->bi_seg_front_size)
+				fbio->bi_seg_front_size = seg_size;
 
-		nr_phys_segs++;
-		bvprv = bv;
-		seg_size = bv->bv_len;
-		highprv = high;
+			nr_phys_segs++;
+			bvprv = bv;
+			seg_size = bv->bv_len;
+			highprv = high;
+		}
 	}
 
-	if (nr_phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size)
+	if (seg_size_ptr)
+		*seg_size_ptr = seg_size;
+
+	return nr_phys_segs;
+}
+
+void blk_recalc_rq_segments(struct request *rq)
+{
+	unsigned int seg_size = 0, phys_segs;
+
+	phys_segs = __blk_recalc_rq_segments(rq->q, rq->bio, &seg_size);
+
+	if (phys_segs == 1 && seg_size > rq->bio->bi_seg_front_size)
 		rq->bio->bi_seg_front_size = seg_size;
 	if (seg_size > rq->biotail->bi_seg_back_size)
 		rq->biotail->bi_seg_back_size = seg_size;
 
-	rq->nr_phys_segments = nr_phys_segs;
+	rq->nr_phys_segments = phys_segs;
 }
 
 void blk_recount_segments(struct request_queue *q, struct bio *bio)
 {
-	struct request rq;
 	struct bio *nxt = bio->bi_next;
-	rq.q = q;
-	rq.bio = rq.biotail = bio;
+
 	bio->bi_next = NULL;
-	blk_recalc_rq_segments(&rq);
+	bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, NULL);
 	bio->bi_next = nxt;
-	bio->bi_phys_segments = rq.nr_phys_segments;
 	bio->bi_flags |= (1 << BIO_SEG_VALID);
 }
 EXPORT_SYMBOL(blk_recount_segments);
diff --git a/block/genhd.c b/block/genhd.c
index e1eadcc..a9ec910 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -256,6 +256,22 @@
 }
 #endif /* CONFIG_PROC_FS */
 
+/**
+ * register_blkdev - register a new block device
+ *
+ * @major: the requested major device number [1..255]. If @major=0, try to
+ *         allocate any unused major number.
+ * @name: the name of the new block device as a zero terminated string
+ *
+ * The @name must be unique within the system.
+ *
+ * The return value depends on the @major input parameter.
+ *  - if a major device number was requested in range [1..255] then the
+ *    function returns zero on success, or a negative error code
+ *  - if any unused major number was requested with @major=0 parameter
+ *    then the return value is the allocated major number in range
+ *    [1..255] or a negative error code otherwise
+ */
 int register_blkdev(unsigned int major, const char *name)
 {
 	struct blk_major_name **n, *p;
diff --git a/crypto/ahash.c b/crypto/ahash.c
index ba5292d..b2d1ee3 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -214,7 +214,7 @@
 	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
 					     "yes" : "no");
 	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
-	seq_printf(m, "digestsize   : %u\n", alg->cra_hash.digestsize);
+	seq_printf(m, "digestsize   : %u\n", alg->cra_ahash.digestsize);
 }
 
 const struct crypto_type crypto_ahash_type = {
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 63719ab..115b1cd 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -24,7 +24,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_amd"
-#define DRV_VERSION "0.3.11"
+#define DRV_VERSION "0.4.1"
 
 /**
  *	timing_setup		-	shared timing computation and load
@@ -145,6 +145,13 @@
 	return ata_sff_prereset(link, deadline);
 }
 
+/**
+ *	amd_cable_detect	-	report cable type
+ *	@ap: port
+ *
+ *	AMD controller/BIOS setups record the cable type in word 0x42
+ */
+
 static int amd_cable_detect(struct ata_port *ap)
 {
 	static const u32 bitmask[2] = {0x03, 0x0C};
@@ -158,6 +165,40 @@
 }
 
 /**
+ *	amd_fifo_setup		-	set the PIO FIFO for ATA/ATAPI
+ *	@ap: ATA interface
+ *	@adev: ATA device
+ *
+ *	Set the PCI fifo for this device according to the devices present
+ *	on the bus at this point in time. We need to turn the post write buffer
+ *	off for ATAPI devices as we may need to issue a word sized write to the
+ *	device as the final I/O
+ */
+
+static void amd_fifo_setup(struct ata_port *ap)
+{
+	struct ata_device *adev;
+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+	static const u8 fifobit[2] = { 0xC0, 0x30};
+	u8 fifo = fifobit[ap->port_no];
+	u8 r;
+
+
+	ata_for_each_dev(adev, &ap->link, ENABLED) {
+		if (adev->class == ATA_DEV_ATAPI)
+			fifo = 0;
+	}
+	if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411) /* FIFO is broken */
+		fifo = 0;
+
+	/* On the later chips the read prefetch bits become no-op bits */
+	pci_read_config_byte(pdev, 0x41, &r);
+	r &= ~fifobit[ap->port_no];
+	r |= fifo;
+	pci_write_config_byte(pdev, 0x41, r);
+}
+
+/**
  *	amd33_set_piomode	-	set initial PIO mode data
  *	@ap: ATA interface
  *	@adev: ATA device
@@ -167,21 +208,25 @@
 
 static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
+	amd_fifo_setup(ap);
 	timing_setup(ap, adev, 0x40, adev->pio_mode, 1);
 }
 
 static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
+	amd_fifo_setup(ap);
 	timing_setup(ap, adev, 0x40, adev->pio_mode, 2);
 }
 
 static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
+	amd_fifo_setup(ap);
 	timing_setup(ap, adev, 0x40, adev->pio_mode, 3);
 }
 
 static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
+	amd_fifo_setup(ap);
 	timing_setup(ap, adev, 0x40, adev->pio_mode, 4);
 }
 
@@ -397,6 +442,16 @@
 	.set_dmamode	= nv133_set_dmamode,
 };
 
+static void amd_clear_fifo(struct pci_dev *pdev)
+{
+	u8 fifo;
+	/* Disable the FIFO, the FIFO logic will re-enable it as
+	   appropriate */
+	pci_read_config_byte(pdev, 0x41, &fifo);
+	fifo &= 0x0F;
+	pci_write_config_byte(pdev, 0x41, fifo);
+}
+
 static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	static const struct ata_port_info info[10] = {
@@ -503,14 +558,8 @@
 
 	if (type < 3)
 		ata_pci_bmdma_clear_simplex(pdev);
-
-	/* Check for AMD7411 */
-	if (type == 3)
-		/* FIFO is broken */
-		pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
-	else
-		pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
-
+	if (pdev->vendor == PCI_VENDOR_ID_AMD)
+		amd_clear_fifo(pdev);
 	/* Cable detection on Nvidia chips doesn't work too well,
 	 * cache BIOS programmed UDMA mode.
 	 */
@@ -536,18 +585,11 @@
 		return rc;
 
 	if (pdev->vendor == PCI_VENDOR_ID_AMD) {
-		u8 fifo;
-		pci_read_config_byte(pdev, 0x41, &fifo);
-		if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
-			/* FIFO is broken */
-			pci_write_config_byte(pdev, 0x41, fifo & 0x0F);
-		else
-			pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
+		amd_clear_fifo(pdev);
 		if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
 		    pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
 			ata_pci_bmdma_clear_simplex(pdev);
 	}
-
 	ata_host_resume(host);
 	return 0;
 }
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index f1bb2f9..b05b86a 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -557,6 +557,9 @@
 		id[83] |= 0x4400;	/* Word 83 is valid and LBA48 */
 		id[86] |= 0x0400;	/* LBA48 on */
 		id[ATA_ID_MAJOR_VER] |= 0x1F;
+		/* Clear the serial number because it's different each boot
+		   which breaks validation on resume */
+		memset(&id[ATA_ID_SERNO], 0x20, ATA_ID_SERNO_LEN);
 	}
 	return err_mask;
 }
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 6c1d778..e3bc1b4 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -283,9 +283,10 @@
 static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
 			unsigned char *buf, unsigned int buflen, int rw)
 {
-	if (ata_id_has_dword_io(dev->id)) {
+	int slop = buflen & 3;
+	/* 32bit I/O capable *and* we need to write a whole number of dwords */
+	if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)) {
 		struct ata_port *ap = dev->link->ap;
-		int slop = buflen & 3;
 		unsigned long flags;
 
 		local_irq_save(flags);
@@ -735,7 +736,7 @@
 	struct ata_port *ap = adev->link->ap;
 	int slop = buflen & 3;
 
-	if (ata_id_has_dword_io(adev->id)) {
+	if (ata_id_has_dword_io(adev->id) && (slop == 0 || slop == 3)) {
 		if (rw == WRITE)
 			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 		else
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 4ae1a41..7007edd 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -3114,19 +3114,17 @@
 		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
 	}
 
-	if (!IS_SOC(hpriv)) {
-		/* Clear any currently outstanding host interrupt conditions */
-		writelfl(0, mmio + hpriv->irq_cause_ofs);
+	/* Clear any currently outstanding host interrupt conditions */
+	writelfl(0, mmio + hpriv->irq_cause_ofs);
 
-		/* and unmask interrupt generation for host regs */
-		writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
+	/* and unmask interrupt generation for host regs */
+	writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
 
-		/*
-		 * enable only global host interrupts for now.
-		 * The per-port interrupts get done later as ports are set up.
-		 */
-		mv_set_main_irq_mask(host, 0, PCI_ERR);
-	}
+	/*
+	 * enable only global host interrupts for now.
+	 * The per-port interrupts get done later as ports are set up.
+	 */
+	mv_set_main_irq_mask(host, 0, PCI_ERR);
 done:
 	return rc;
 }
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 144a49f..8733a2e 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -901,7 +901,7 @@
 		clock_l(); udelay(5);
 		for (i = 128; i != 0; i >>= 1) {   /* write command out */
 			tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) |
-			    (data & i) ? CONFIG1_PROMDATA : 0;
+			    ((data & i) ? CONFIG1_PROMDATA : 0);
 			if (lanai->conf1 != tmp) {
 				set_config1(tmp);
 				udelay(5);	/* Let new data settle */
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index d2cb67b..b5a0611 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3611,11 +3611,15 @@
 		schedule_timeout_uninterruptible(30*HZ);
 
 		/* Now try to get the controller to respond to a no-op */
-		for (i=0; i<12; i++) {
+		for (i=0; i<30; i++) {
 			if (cciss_noop(pdev) == 0)
 				break;
-			else
-				printk("cciss: no-op failed%s\n", (i < 11 ? "; re-trying" : ""));
+
+			schedule_timeout_uninterruptible(HZ);
+		}
+		if (i == 30) {
+			printk(KERN_ERR "cciss: controller seems dead\n");
+			return -EBUSY;
 		}
 	}
 
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 918ef725..b6c8ce2 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -40,6 +40,7 @@
 #include <linux/hdreg.h>
 #include <linux/cdrom.h>
 #include <linux/module.h>
+#include <linux/scatterlist.h>
 
 #include <xen/xenbus.h>
 #include <xen/grant_table.h>
@@ -82,6 +83,7 @@
 	enum blkif_state connected;
 	int ring_ref;
 	struct blkif_front_ring ring;
+	struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 	unsigned int evtchn, irq;
 	struct request_queue *rq;
 	struct work_struct work;
@@ -204,12 +206,11 @@
 	struct blkfront_info *info = req->rq_disk->private_data;
 	unsigned long buffer_mfn;
 	struct blkif_request *ring_req;
-	struct req_iterator iter;
-	struct bio_vec *bvec;
 	unsigned long id;
 	unsigned int fsect, lsect;
-	int ref;
+	int i, ref;
 	grant_ref_t gref_head;
+	struct scatterlist *sg;
 
 	if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
 		return 1;
@@ -238,12 +239,13 @@
 	if (blk_barrier_rq(req))
 		ring_req->operation = BLKIF_OP_WRITE_BARRIER;
 
-	ring_req->nr_segments = 0;
-	rq_for_each_segment(bvec, req, iter) {
-		BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST);
-		buffer_mfn = pfn_to_mfn(page_to_pfn(bvec->bv_page));
-		fsect = bvec->bv_offset >> 9;
-		lsect = fsect + (bvec->bv_len >> 9) - 1;
+	ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
+	BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
+	for_each_sg(info->sg, sg, ring_req->nr_segments, i) {
+		buffer_mfn = pfn_to_mfn(page_to_pfn(sg_page(sg)));
+		fsect = sg->offset >> 9;
+		lsect = fsect + (sg->length >> 9) - 1;
 		/* install a grant reference. */
 		ref = gnttab_claim_grant_reference(&gref_head);
 		BUG_ON(ref == -ENOSPC);
@@ -254,16 +256,12 @@
 				buffer_mfn,
 				rq_data_dir(req) );
 
-		info->shadow[id].frame[ring_req->nr_segments] =
-				mfn_to_pfn(buffer_mfn);
-
-		ring_req->seg[ring_req->nr_segments] =
+		info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
+		ring_req->seg[i] =
 				(struct blkif_request_segment) {
 					.gref       = ref,
 					.first_sect = fsect,
 					.last_sect  = lsect };
-
-		ring_req->nr_segments++;
 	}
 
 	info->ring.req_prod_pvt++;
@@ -622,6 +620,8 @@
 	SHARED_RING_INIT(sring);
 	FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
 
+	sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
 	err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
 	if (err < 0) {
 		free_page((unsigned long)sring);
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 733028b..1c3a8c5 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -452,6 +452,59 @@
 	kfree(modes);
 	kfree(enabled);
 }
+
+/**
+ * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
+ * @encoder: encoder to test
+ * @crtc: crtc to test
+ *
+ * Return false if @encoder can't be driven by @crtc, true otherwise.
+ */
+static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+				struct drm_crtc *crtc)
+{
+	struct drm_device *dev;
+	struct drm_crtc *tmp;
+	int crtc_mask = 1;
+
+	WARN(!crtc, "checking null crtc?");
+
+	dev = crtc->dev;
+
+	list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
+		if (tmp == crtc)
+			break;
+		crtc_mask <<= 1;
+	}
+
+	if (encoder->possible_crtcs & crtc_mask)
+		return true;
+	return false;
+}
+
+/*
+ * Check the CRTC we're going to map each output to vs. its current
+ * CRTC.  If they don't match, we have to disable the output and the CRTC
+ * since the driver will have to re-route things.
+ */
+static void
+drm_crtc_prepare_encoders(struct drm_device *dev)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	struct drm_encoder *encoder;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		encoder_funcs = encoder->helper_private;
+		/* Disable unused encoders */
+		if (encoder->crtc == NULL)
+			(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+		/* Disable encoders whose CRTC is about to change */
+		if (encoder_funcs->get_crtc &&
+		    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
+			(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+	}
+}
+
 /**
  * drm_crtc_set_mode - set a mode
  * @crtc: CRTC to program
@@ -547,6 +600,8 @@
 		encoder_funcs->prepare(encoder);
 	}
 
+	drm_crtc_prepare_encoders(dev);
+
 	crtc_funcs->prepare(crtc);
 
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
@@ -617,7 +672,7 @@
 	struct drm_device *dev;
 	struct drm_crtc **save_crtcs, *new_crtc;
 	struct drm_encoder **save_encoders, *new_encoder;
-	struct drm_framebuffer *old_fb;
+	struct drm_framebuffer *old_fb = NULL;
 	bool save_enabled;
 	bool mode_changed = false;
 	bool fb_changed = false;
@@ -668,9 +723,10 @@
 	 * and then just flip_or_move it */
 	if (set->crtc->fb != set->fb) {
 		/* If we have no fb then treat it as a full mode set */
-		if (set->crtc->fb == NULL)
+		if (set->crtc->fb == NULL) {
+			DRM_DEBUG("crtc has no fb, full mode set\n");
 			mode_changed = true;
-		else if ((set->fb->bits_per_pixel !=
+		} else if ((set->fb->bits_per_pixel !=
 			 set->crtc->fb->bits_per_pixel) ||
 			 set->fb->depth != set->crtc->fb->depth)
 			fb_changed = true;
@@ -682,7 +738,7 @@
 		fb_changed = true;
 
 	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
-		DRM_DEBUG("modes are different\n");
+		DRM_DEBUG("modes are different, full mode set\n");
 		drm_mode_debug_printmodeline(&set->crtc->mode);
 		drm_mode_debug_printmodeline(set->mode);
 		mode_changed = true;
@@ -708,6 +764,7 @@
 		}
 
 		if (new_encoder != connector->encoder) {
+			DRM_DEBUG("encoder changed, full mode switch\n");
 			mode_changed = true;
 			connector->encoder = new_encoder;
 		}
@@ -734,10 +791,20 @@
 			if (set->connectors[ro] == connector)
 				new_crtc = set->crtc;
 		}
+
+		/* Make sure the new CRTC will work with the encoder */
+		if (new_crtc &&
+		    !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
+			ret = -EINVAL;
+			goto fail_set_mode;
+		}
 		if (new_crtc != connector->encoder->crtc) {
+			DRM_DEBUG("crtc changed, full mode switch\n");
 			mode_changed = true;
 			connector->encoder->crtc = new_crtc;
 		}
+		DRM_DEBUG("setting connector %d crtc to %p\n",
+			  connector->base.id, new_crtc);
 	}
 
 	/* mode_set_base is not a required function */
@@ -781,6 +848,7 @@
 
 fail_set_mode:
 	set->crtc->enabled = save_enabled;
+	set->crtc->fb = old_fb;
 	count = 0;
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		if (!connector->encoder)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 5a4d324..a839a28 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -125,7 +125,7 @@
 		DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
 		goto bad;
 	}
-	if (edid->revision <= 0 || edid->revision > 3) {
+	if (edid->revision > 3) {
 		DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision);
 		goto bad;
 	}
@@ -320,10 +320,10 @@
 	mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
 
 	mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
-	mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) |
+	mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) |
 					      pt->vsync_offset_lo);
 	mode->vsync_end = mode->vsync_start +
-		((pt->vsync_pulse_width_hi << 8) |
+		((pt->vsync_pulse_width_hi << 4) |
 		 pt->vsync_pulse_width_lo);
 	mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
 
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 3795dbc..93e677a 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -435,6 +435,8 @@
  */
 void drm_vblank_put(struct drm_device *dev, int crtc)
 {
+	BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0);
+
 	/* Last user schedules interrupt disable */
 	if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
 		mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
@@ -460,8 +462,9 @@
 	 * so that interrupts remain enabled in the interim.
 	 */
 	if (!dev->vblank_inmodeset[crtc]) {
-		dev->vblank_inmodeset[crtc] = 1;
-		drm_vblank_get(dev, crtc);
+		dev->vblank_inmodeset[crtc] = 0x1;
+		if (drm_vblank_get(dev, crtc) == 0)
+			dev->vblank_inmodeset[crtc] |= 0x2;
 	}
 }
 EXPORT_SYMBOL(drm_vblank_pre_modeset);
@@ -473,9 +476,12 @@
 	if (dev->vblank_inmodeset[crtc]) {
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
 		dev->vblank_disable_allowed = 1;
-		dev->vblank_inmodeset[crtc] = 0;
 		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-		drm_vblank_put(dev, crtc);
+
+		if (dev->vblank_inmodeset[crtc] & 0x2)
+			drm_vblank_put(dev, crtc);
+
+		dev->vblank_inmodeset[crtc] = 0;
 	}
 }
 EXPORT_SYMBOL(drm_vblank_post_modeset);
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 2d797ff..6dab63b 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -811,7 +811,7 @@
 	dev_priv->hws_map.flags = 0;
 	dev_priv->hws_map.mtrr = 0;
 
-	drm_core_ioremap(&dev_priv->hws_map, dev);
+	drm_core_ioremap_wc(&dev_priv->hws_map, dev);
 	if (dev_priv->hws_map.handle == NULL) {
 		i915_dma_cleanup(dev);
 		dev_priv->status_gfx_addr = 0;
@@ -1090,6 +1090,11 @@
         dev_priv->mm.gtt_mapping =
 		io_mapping_create_wc(dev->agp->base,
 				     dev->agp->agp_info.aper_size * 1024*1024);
+	if (dev_priv->mm.gtt_mapping == NULL) {
+		ret = -EIO;
+		goto out_rmmap;
+	}
+
 	/* Set up a WC MTRR for non-PAT systems.  This is more common than
 	 * one would think, because the kernel disables PAT on first
 	 * generation Core chips because WC PAT gets overridden by a UC
@@ -1122,7 +1127,7 @@
 	if (!I915_NEED_GFX_HWS(dev)) {
 		ret = i915_init_phys_hws(dev);
 		if (ret != 0)
-			goto out_rmmap;
+			goto out_iomapfree;
 	}
 
 	/* On the 945G/GM, the chipset reports the MSI capability on the
@@ -1161,6 +1166,8 @@
 
 	return 0;
 
+out_iomapfree:
+	io_mapping_free(dev_priv->mm.gtt_mapping);
 out_rmmap:
 	iounmap(dev_priv->regs);
 free_priv:
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 0692622..b293ef0 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -68,9 +68,11 @@
 	i915_save_state(dev);
 
 	/* If KMS is active, we do the leavevt stuff here */
-	if (drm_core_check_feature(dev, DRIVER_MODESET) && i915_gem_idle(dev)) {
-		dev_err(&dev->pdev->dev, "GEM idle failed, aborting suspend\n");
-		return -EBUSY;
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		if (i915_gem_idle(dev))
+			dev_err(&dev->pdev->dev,
+				"GEM idle failed, resume may fail\n");
+		drm_irq_uninstall(dev);
 	}
 
 	intel_opregion_free(dev);
@@ -108,6 +110,8 @@
 		if (ret != 0)
 			ret = -1;
 		mutex_unlock(&dev->struct_mutex);
+
+		drm_irq_install(dev);
 	}
 
 	return ret;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 25b3374..c29feb9 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -211,7 +211,7 @@
 
 	vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
 	unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
-						      user_data, length);
+						      user_data, length, length);
 	io_mapping_unmap_atomic(vaddr_atomic);
 	if (unwritten)
 		return -EFAULT;
@@ -1051,6 +1051,9 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t seqno;
 
+	if (!dev_priv->hw_status_page)
+		return;
+
 	seqno = i915_get_gem_seqno(dev);
 
 	while (!list_empty(&dev_priv->mm.request_list)) {
@@ -3545,7 +3548,7 @@
 	user_data = (char __user *) (uintptr_t) args->data_ptr;
 	obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
 
-	DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size);
+	DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size);
 	ret = copy_from_user(obj_addr, user_data, args->size);
 	if (ret)
 		return -EFAULT;
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 65be30d..fc28e2b 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -111,6 +111,12 @@
 	panel_fixed_mode->clock = dvo_timing->clock * 10;
 	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
 
+	/* Some VBTs have bogus h/vtotal values */
+	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
+		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
+	if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
+		panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
+
 	drm_mode_set_name(panel_fixed_mode);
 
 	dev_priv->vbt_mode = panel_fixed_mode;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 65b635c..a283427 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -217,7 +217,7 @@
     return false;
 }
 
-#define INTELPllInvalid(s)   do { DRM_DEBUG(s); return false; } while (0)
+#define INTELPllInvalid(s)   do { /* DRM_DEBUG(s); */ return false; } while (0)
 /**
  * Returns whether the given set of divisors are valid for a given refclk with
  * the given connectors.
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
index 9fee3ca..9aefb5e 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -79,10 +79,11 @@
 	.getsda		= ioc_getsda,
 	.getscl		= ioc_getscl,
 	.udelay		= 80,
-	.timeout	= 100
+	.timeout	= HZ,
 };
 
 static struct i2c_adapter ioc_ops = {
+	.nr			= 0,
 	.algo_data		= &ioc_data,
 };
 
@@ -90,7 +91,7 @@
 {
 	force_ones = FORCE_ONES | SCL | SDA;
 
-	return i2c_bit_add_bus(&ioc_ops);
+	return i2c_bit_add_numbered_bus(&ioc_ops);
 }
 
 module_init(i2c_ioc_init);
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index edab519..a7c5990 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -72,7 +72,7 @@
 {
 	int timeout = 500;
 
-	while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF))
+	while ((inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF) && --timeout)
 		udelay(1);
 
 	if (!timeout) {
@@ -88,7 +88,7 @@
 {
 	int timeout = 500;
 
-	while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF))
+	while ((~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF) && --timeout)
 		udelay(1);
 
 	if (!timeout) {
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index 8e84679..c016f7a 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -114,7 +114,7 @@
 	drv_data->algo_data.getsda = ixp2000_bit_getsda;
 	drv_data->algo_data.getscl = ixp2000_bit_getscl;
 	drv_data->algo_data.udelay = 6;
-	drv_data->algo_data.timeout = 100;
+	drv_data->algo_data.timeout = HZ;
 
 	strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
 		sizeof(drv_data->adapter.name));
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 6af6814..bdb1f751 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -644,7 +644,7 @@
 
 	i2c_pxa_start_message(i2c);
 
-	while (timeout-- && i2c->msg_num > 0) {
+	while (i2c->msg_num > 0 && --timeout) {
 		i2c_pxa_handler(0, i2c);
 		udelay(10);
 	}
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
index 162b74a..42df0ec 100644
--- a/drivers/i2c/busses/scx200_i2c.c
+++ b/drivers/i2c/busses/scx200_i2c.c
@@ -76,7 +76,7 @@
 	.getsda		= scx200_i2c_getsda,
 	.getscl		= scx200_i2c_getscl,
 	.udelay		= 10,
-	.timeout	= 100,
+	.timeout	= HZ,
 };
 
 static struct i2c_adapter scx200_i2c_ops = {
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index b1c9abe..e7d9848 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1831,7 +1831,8 @@
 	case I2C_SMBUS_QUICK:
 		msg[0].len = 0;
 		/* Special case: The read/write field is used as data */
-		msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0;
+		msg[0].flags = flags | (read_write == I2C_SMBUS_READ ?
+					I2C_M_RD : 0);
 		num = 1;
 		break;
 	case I2C_SMBUS_BYTE:
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index c171988..7e13d2d 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -35,6 +35,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
 #include <linux/smp_lock.h>
+#include <linux/jiffies.h>
 #include <asm/uaccess.h>
 
 static struct i2c_driver i2cdev_driver;
@@ -422,7 +423,10 @@
 		client->adapter->retries = arg;
 		break;
 	case I2C_TIMEOUT:
-		client->adapter->timeout = arg;
+		/* For historical reasons, user-space sets the timeout
+		 * value in units of 10 ms.
+		 */
+		client->adapter->timeout = msecs_to_jiffies(arg * 10);
 		break;
 	default:
 		/* NOTE:  returning a fault code here could cause trouble
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 3dad229..e072903 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -46,7 +46,7 @@
 	  SMART parameters from disk drives.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called ide.
+	  module will be called ide-core.ko.
 
 	  For further information, please read <file:Documentation/ide/ide.txt>.
 
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index 69660a4..77267c8 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -166,7 +166,7 @@
 	 * Check for broken FIFO support.
 	 */
 	if (dev->vendor == PCI_VENDOR_ID_AMD &&
-	    dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411)
+	    dev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
 		t &= 0x0f;
 	else
 		t |= 0xf0;
diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c
index b2735d2..ecd1e62 100644
--- a/drivers/ide/atiixp.c
+++ b/drivers/ide/atiixp.c
@@ -52,7 +52,7 @@
 {
 	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	unsigned long flags;
-	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+	int timing_shift = (drive->dn ^ 1) * 8;
 	u32 pio_timing_data;
 	u16 pio_mode_data;
 
@@ -85,7 +85,7 @@
 {
 	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
 	unsigned long flags;
-	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+	int timing_shift = (drive->dn ^ 1) * 8;
 	u32 tmp32;
 	u16 tmp16;
 	u16 udma_ctl = 0;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 0bfeb0c..ddfbea4 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -55,7 +55,7 @@
 
 static DEFINE_MUTEX(idecd_ref_mutex);
 
-static void ide_cd_release(struct kref *);
+static void ide_cd_release(struct device *);
 
 static struct cdrom_info *ide_cd_get(struct gendisk *disk)
 {
@@ -67,7 +67,7 @@
 		if (ide_device_get(cd->drive))
 			cd = NULL;
 		else
-			kref_get(&cd->kref);
+			get_device(&cd->dev);
 
 	}
 	mutex_unlock(&idecd_ref_mutex);
@@ -79,7 +79,7 @@
 	ide_drive_t *drive = cd->drive;
 
 	mutex_lock(&idecd_ref_mutex);
-	kref_put(&cd->kref, ide_cd_release);
+	put_device(&cd->dev);
 	ide_device_put(drive);
 	mutex_unlock(&idecd_ref_mutex);
 }
@@ -194,6 +194,14 @@
 			bio_sectors = max(bio_sectors(failed_command->bio), 4U);
 			sector &= ~(bio_sectors - 1);
 
+			/*
+			 * The SCSI specification allows for the value
+			 * returned by READ CAPACITY to be up to 75 2K
+			 * sectors past the last readable block.
+			 * Therefore, if we hit a medium error within the
+			 * last 75 2K sectors, we decrease the saved size
+			 * value.
+			 */
 			if (sector < get_capacity(info->disk) &&
 			    drive->probed_capacity - sector < 4 * 75)
 				set_capacity(info->disk, sector);
@@ -1790,15 +1798,17 @@
 	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
 
 	ide_proc_unregister_driver(drive, info->driver);
-
+	device_del(&info->dev);
 	del_gendisk(info->disk);
 
-	ide_cd_put(info);
+	mutex_lock(&idecd_ref_mutex);
+	put_device(&info->dev);
+	mutex_unlock(&idecd_ref_mutex);
 }
 
-static void ide_cd_release(struct kref *kref)
+static void ide_cd_release(struct device *dev)
 {
-	struct cdrom_info *info = to_ide_drv(kref, cdrom_info);
+	struct cdrom_info *info = to_ide_drv(dev, cdrom_info);
 	struct cdrom_device_info *devinfo = &info->devinfo;
 	ide_drive_t *drive = info->drive;
 	struct gendisk *g = info->disk;
@@ -1997,7 +2007,12 @@
 
 	ide_init_disk(g, drive);
 
-	kref_init(&info->kref);
+	info->dev.parent = &drive->gendev;
+	info->dev.release = ide_cd_release;
+	dev_set_name(&info->dev, dev_name(&drive->gendev));
+
+	if (device_register(&info->dev))
+		goto out_free_disk;
 
 	info->drive = drive;
 	info->driver = &ide_cdrom_driver;
@@ -2011,7 +2026,7 @@
 	g->driverfs_dev = &drive->gendev;
 	g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
 	if (ide_cdrom_setup(drive)) {
-		ide_cd_release(&info->kref);
+		put_device(&info->dev);
 		goto failed;
 	}
 
@@ -2021,6 +2036,8 @@
 	add_disk(g);
 	return 0;
 
+out_free_disk:
+	put_disk(g);
 out_free_cd:
 	kfree(info);
 failed:
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index ac40d6c..c878bfc 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -80,7 +80,7 @@
 	ide_drive_t		*drive;
 	struct ide_driver	*driver;
 	struct gendisk		*disk;
-	struct kref		kref;
+	struct device		dev;
 
 	/* Buffer for table of contents.  NULL if we haven't allocated
 	   a TOC buffer for this device yet. */
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index 7857b20..0471094 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -25,7 +25,7 @@
 
 static DEFINE_MUTEX(ide_disk_ref_mutex);
 
-static void ide_disk_release(struct kref *);
+static void ide_disk_release(struct device *);
 
 static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
 {
@@ -37,7 +37,7 @@
 		if (ide_device_get(idkp->drive))
 			idkp = NULL;
 		else
-			kref_get(&idkp->kref);
+			get_device(&idkp->dev);
 	}
 	mutex_unlock(&ide_disk_ref_mutex);
 	return idkp;
@@ -48,7 +48,7 @@
 	ide_drive_t *drive = idkp->drive;
 
 	mutex_lock(&ide_disk_ref_mutex);
-	kref_put(&idkp->kref, ide_disk_release);
+	put_device(&idkp->dev);
 	ide_device_put(drive);
 	mutex_unlock(&ide_disk_ref_mutex);
 }
@@ -66,17 +66,18 @@
 	struct gendisk *g = idkp->disk;
 
 	ide_proc_unregister_driver(drive, idkp->driver);
-
+	device_del(&idkp->dev);
 	del_gendisk(g);
-
 	drive->disk_ops->flush(drive);
 
-	ide_disk_put(idkp);
+	mutex_lock(&ide_disk_ref_mutex);
+	put_device(&idkp->dev);
+	mutex_unlock(&ide_disk_ref_mutex);
 }
 
-static void ide_disk_release(struct kref *kref)
+static void ide_disk_release(struct device *dev)
 {
-	struct ide_disk_obj *idkp = to_ide_drv(kref, ide_disk_obj);
+	struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj);
 	ide_drive_t *drive = idkp->drive;
 	struct gendisk *g = idkp->disk;
 
@@ -348,7 +349,12 @@
 
 	ide_init_disk(g, drive);
 
-	kref_init(&idkp->kref);
+	idkp->dev.parent = &drive->gendev;
+	idkp->dev.release = ide_disk_release;
+	dev_set_name(&idkp->dev, dev_name(&drive->gendev));
+
+	if (device_register(&idkp->dev))
+		goto out_free_disk;
 
 	idkp->drive = drive;
 	idkp->driver = &ide_gd_driver;
@@ -373,6 +379,8 @@
 	add_disk(g);
 	return 0;
 
+out_free_disk:
+	put_disk(g);
 out_free_idkp:
 	kfree(idkp);
 failed:
diff --git a/drivers/ide/ide-gd.h b/drivers/ide/ide-gd.h
index a86779f..b604bdd 100644
--- a/drivers/ide/ide-gd.h
+++ b/drivers/ide/ide-gd.h
@@ -17,7 +17,7 @@
 	ide_drive_t		*drive;
 	struct ide_driver	*driver;
 	struct gendisk		*disk;
-	struct kref		kref;
+	struct device		dev;
 	unsigned int		openers;	/* protected by BKL for now */
 
 	/* Last failed packet command */
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index d7ecd3c..bb450a7 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -169,7 +169,7 @@
 	ide_drive_t		*drive;
 	struct ide_driver	*driver;
 	struct gendisk		*disk;
-	struct kref		kref;
+	struct device		dev;
 
 	/*
 	 *	failed_pc points to the last failed packet command, or contains
@@ -267,7 +267,7 @@
 
 static struct class *idetape_sysfs_class;
 
-static void ide_tape_release(struct kref *);
+static void ide_tape_release(struct device *);
 
 static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
 {
@@ -279,7 +279,7 @@
 		if (ide_device_get(tape->drive))
 			tape = NULL;
 		else
-			kref_get(&tape->kref);
+			get_device(&tape->dev);
 	}
 	mutex_unlock(&idetape_ref_mutex);
 	return tape;
@@ -290,7 +290,7 @@
 	ide_drive_t *drive = tape->drive;
 
 	mutex_lock(&idetape_ref_mutex);
-	kref_put(&tape->kref, ide_tape_release);
+	put_device(&tape->dev);
 	ide_device_put(drive);
 	mutex_unlock(&idetape_ref_mutex);
 }
@@ -308,7 +308,7 @@
 	mutex_lock(&idetape_ref_mutex);
 	tape = idetape_devs[i];
 	if (tape)
-		kref_get(&tape->kref);
+		get_device(&tape->dev);
 	mutex_unlock(&idetape_ref_mutex);
 	return tape;
 }
@@ -2256,15 +2256,17 @@
 	idetape_tape_t *tape = drive->driver_data;
 
 	ide_proc_unregister_driver(drive, tape->driver);
-
+	device_del(&tape->dev);
 	ide_unregister_region(tape->disk);
 
-	ide_tape_put(tape);
+	mutex_lock(&idetape_ref_mutex);
+	put_device(&tape->dev);
+	mutex_unlock(&idetape_ref_mutex);
 }
 
-static void ide_tape_release(struct kref *kref)
+static void ide_tape_release(struct device *dev)
 {
-	struct ide_tape_obj *tape = to_ide_drv(kref, ide_tape_obj);
+	struct ide_tape_obj *tape = to_ide_drv(dev, ide_tape_obj);
 	ide_drive_t *drive = tape->drive;
 	struct gendisk *g = tape->disk;
 
@@ -2407,7 +2409,12 @@
 
 	ide_init_disk(g, drive);
 
-	kref_init(&tape->kref);
+	tape->dev.parent = &drive->gendev;
+	tape->dev.release = ide_tape_release;
+	dev_set_name(&tape->dev, dev_name(&drive->gendev));
+
+	if (device_register(&tape->dev))
+		goto out_free_disk;
 
 	tape->drive = drive;
 	tape->driver = &idetape_driver;
@@ -2436,6 +2443,8 @@
 
 	return 0;
 
+out_free_disk:
+	put_disk(g);
 out_free_tape:
 	kfree(tape);
 failed:
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 258805d..0920e3b 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -337,6 +337,7 @@
 	int a, b, i, j = 1;
 	unsigned int *dev_param_mask = (unsigned int *)kp->arg;
 
+	/* controller . device (0 or 1) [ : 1 (set) | 0 (clear) ] */
 	if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 &&
 	    sscanf(s, "%d.%d", &a, &b) != 2)
 		return -EINVAL;
@@ -349,7 +350,7 @@
 	if (j)
 		*dev_param_mask |= (1 << i);
 	else
-		*dev_param_mask &= (1 << i);
+		*dev_param_mask &= ~(1 << i);
 
 	return 0;
 }
@@ -392,6 +393,8 @@
 {
 	int a, b, c = 0, h = 0, s = 0, i, j = 1;
 
+	/* controller . device (0 or 1) : Cylinders , Heads , Sectors */
+	/* controller . device (0 or 1) : 1 (use CHS) | 0 (ignore CHS) */
 	if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 &&
 	    sscanf(str, "%d.%d:%d", &a, &b, &j) != 3)
 		return -EINVAL;
@@ -407,7 +410,7 @@
 	if (j)
 		ide_disks |= (1 << i);
 	else
-		ide_disks &= (1 << i);
+		ide_disks &= ~(1 << i);
 
 	ide_disks_chs[i].cyl  = c;
 	ide_disks_chs[i].head = h;
@@ -469,6 +472,8 @@
 {
 	int i, j = 1;
 
+	/* controller (ignore) */
+	/* controller : 1 (ignore) | 0 (use) */
 	if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1)
 		return -EINVAL;
 
@@ -478,7 +483,7 @@
 	if (j)
 		ide_ignore_cable |= (1 << i);
 	else
-		ide_ignore_cable &= (1 << i);
+		ide_ignore_cable &= ~(1 << i);
 
 	return 0;
 }
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
index e1c4f54..13b8153 100644
--- a/drivers/ide/it821x.c
+++ b/drivers/ide/it821x.c
@@ -5,9 +5,8 @@
  *  May be copied or modified under the terms of the GNU General Public License
  *  Based in part on the ITE vendor provided SCSI driver.
  *
- *  Documentation available from
- * 	http://www.ite.com.tw/pc/IT8212F_V04.pdf
- *  Some other documents are NDA.
+ *  Documentation:
+ *	Datasheet is freely available, some other documents under NDA.
  *
  *  The ITE8212 isn't exactly a standard IDE controller. It has two
  *  modes. In pass through mode then it is an IDE controller. In its smart
diff --git a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h
index 2727bcd..467373c 100644
--- a/drivers/ieee1394/dma.h
+++ b/drivers/ieee1394/dma.h
@@ -12,6 +12,7 @@
 
 #include <asm/types.h>
 
+struct file;
 struct pci_dev;
 struct scatterlist;
 struct vm_area_struct;
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 2beb8d9..8723380 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -1275,7 +1275,7 @@
 	unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
 }
 
-module_init(ieee1394_init);
+fs_initcall(ieee1394_init);
 module_exit(ieee1394_cleanup);
 
 /* Exported symbols */
@@ -1314,6 +1314,7 @@
 EXPORT_SYMBOL(hpsb_make_phypacket);
 EXPORT_SYMBOL(hpsb_read);
 EXPORT_SYMBOL(hpsb_write);
+EXPORT_SYMBOL(hpsb_lock);
 EXPORT_SYMBOL(hpsb_packet_success);
 
 /** highlevel.c **/
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 10c3d9f..675b313 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -501,8 +501,6 @@
 	if (length == 0)
 		return -EINVAL;
 
-	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
-
 	packet = hpsb_make_readpacket(host, node, addr, length);
 
 	if (!packet) {
@@ -550,8 +548,6 @@
 	if (length == 0)
 		return -EINVAL;
 
-	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
-
 	packet = hpsb_make_writepacket(host, node, addr, buffer, length);
 
 	if (!packet)
@@ -570,3 +566,30 @@
 
 	return retval;
 }
+
+int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+	      u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
+{
+	struct hpsb_packet *packet;
+	int retval = 0;
+
+	packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
+	if (!packet)
+		return -ENOMEM;
+
+	packet->generation = generation;
+	retval = hpsb_send_packet_and_wait(packet);
+	if (retval < 0)
+		goto hpsb_lock_fail;
+
+	retval = hpsb_packet_success(packet);
+
+	if (retval == 0)
+		*data = packet->data[0];
+
+hpsb_lock_fail:
+	hpsb_free_tlabel(packet);
+	hpsb_free_packet(packet);
+
+	return retval;
+}
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index d2d5bc3..20b693b 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -30,6 +30,8 @@
 	      u64 addr, quadlet_t *buffer, size_t length);
 int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 	       u64 addr, quadlet_t *buffer, size_t length);
+int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+	      u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
 
 #ifdef HPSB_DEBUG_TLABELS
 extern spinlock_t hpsb_tlabel_lock;
diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h
index b5de5f2..c2089c0 100644
--- a/drivers/ieee1394/iso.h
+++ b/drivers/ieee1394/iso.h
@@ -13,6 +13,7 @@
 #define IEEE1394_ISO_H
 
 #include <linux/spinlock_types.h>
+#include <linux/wait.h>
 #include <asm/atomic.h>
 #include <asm/types.h>
 
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 906c5a9..53aada5 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -971,6 +971,9 @@
 	ud->ud_kv = ud_kv;
 	ud->id = (*id)++;
 
+	/* inherit vendor_id from root directory if none exists in unit dir */
+	ud->vendor_id = ne->vendor_id;
+
 	csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) {
 		switch (kv->key.id) {
 		case CSR1212_KV_ID_VENDOR:
@@ -1265,7 +1268,8 @@
 		csr1212_destroy_csr(csr);
 	}
 
-	/* Mark the node current */
+	/* Finally, mark the node current */
+	smp_wmb();
 	ne->generation = generation;
 
 	if (ne->in_limbo) {
@@ -1798,7 +1802,7 @@
 {
 	packet->host = ne->host;
 	packet->generation = ne->generation;
-	barrier();
+	smp_rmb();
 	packet->node_id = ne->nodeid;
 }
 
@@ -1807,7 +1811,7 @@
 {
 	unsigned int generation = ne->generation;
 
-	barrier();
+	smp_rmb();
 	return hpsb_write(ne->host, ne->nodeid, generation,
 			  addr, buffer, length);
 }
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 15ea097..ee5acdb 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -21,9 +21,11 @@
 #define _IEEE1394_NODEMGR_H
 
 #include <linux/device.h>
+#include <asm/system.h>
 #include <asm/types.h>
 
 #include "ieee1394_core.h"
+#include "ieee1394_transactions.h"
 #include "ieee1394_types.h"
 
 struct csr1212_csr;
@@ -154,6 +156,22 @@
 void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet);
 int hpsb_node_write(struct node_entry *ne, u64 addr,
 		    quadlet_t *buffer, size_t length);
+static inline int hpsb_node_read(struct node_entry *ne, u64 addr,
+				 quadlet_t *buffer, size_t length)
+{
+	unsigned int g = ne->generation;
+
+	smp_rmb();
+	return hpsb_read(ne->host, ne->nodeid, g, addr, buffer, length);
+}
+static inline int hpsb_node_lock(struct node_entry *ne, u64 addr, int extcode,
+				 quadlet_t *buffer, quadlet_t arg)
+{
+	unsigned int g = ne->generation;
+
+	smp_rmb();
+	return hpsb_lock(ne->host, ne->nodeid, g, addr, extcode, buffer, arg);
+}
 int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *));
 
 int init_ieee1394_nodemgr(void);
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
index 712220c..7f16d75 100644
--- a/drivers/isdn/sc/shmem.c
+++ b/drivers/isdn/sc/shmem.c
@@ -54,7 +54,7 @@
 	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 	pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
 		((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
-	pr_debug("%s: copying %d bytes from %#lx to %#lx\n",
+	pr_debug("%s: copying %zu bytes from %#lx to %#lx\n",
 		sc_adapter[card]->devicename, n,
 		(unsigned long) src,
 		sc_adapter[card]->rambase + ((unsigned long) dest %0x4000));
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 01e3cff..e246642 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1237,8 +1237,9 @@
 	update_head_pos(mirror, r1_bio);
 
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
-		md_done_sync(mddev, r1_bio->sectors, uptodate);
+		sector_t s = r1_bio->sectors;
 		put_buf(r1_bio);
+		md_done_sync(mddev, s, uptodate);
 	}
 }
 
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 6736d6d..7301631 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1236,6 +1236,7 @@
 	/* for reconstruct, we always reschedule after a read.
 	 * for resync, only after all reads
 	 */
+	rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev);
 	if (test_bit(R10BIO_IsRecover, &r10_bio->state) ||
 	    atomic_dec_and_test(&r10_bio->remaining)) {
 		/* we have read all the blocks,
@@ -1243,7 +1244,6 @@
 		 */
 		reschedule_retry(r10_bio);
 	}
-	rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev);
 }
 
 static void end_sync_write(struct bio *bio, int error)
@@ -1264,11 +1264,13 @@
 
 	update_head_pos(i, r10_bio);
 
+	rdev_dec_pending(conf->mirrors[d].rdev, mddev);
 	while (atomic_dec_and_test(&r10_bio->remaining)) {
 		if (r10_bio->master_bio == NULL) {
 			/* the primary of several recovery bios */
-			md_done_sync(mddev, r10_bio->sectors, 1);
+			sector_t s = r10_bio->sectors;
 			put_buf(r10_bio);
+			md_done_sync(mddev, s, 1);
 			break;
 		} else {
 			r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
@@ -1276,7 +1278,6 @@
 			r10_bio = r10_bio2;
 		}
 	}
-	rdev_dec_pending(conf->mirrors[d].rdev, mddev);
 }
 
 /*
@@ -1749,8 +1750,6 @@
 	if (!go_faster && conf->nr_waiting)
 		msleep_interruptible(1000);
 
-	bitmap_cond_end_sync(mddev->bitmap, sector_nr);
-
 	/* Again, very different code for resync and recovery.
 	 * Both must result in an r10bio with a list of bios that
 	 * have bi_end_io, bi_sector, bi_bdev set,
@@ -1886,6 +1885,8 @@
 		/* resync. Schedule a read for every block at this virt offset */
 		int count = 0;
 
+		bitmap_cond_end_sync(mddev->bitmap, sector_nr);
+
 		if (!bitmap_start_sync(mddev->bitmap, sector_nr,
 				       &sync_blocks, mddev->degraded) &&
 		    !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
@@ -2010,13 +2011,13 @@
 	/* There is nowhere to write, so all non-sync
 	 * drives must be failed, so try the next chunk...
 	 */
-	{
-	sector_t sec = max_sector - sector_nr;
-	sectors_skipped += sec;
+	if (sector_nr + max_sync < max_sector)
+		max_sector = sector_nr + max_sync;
+
+	sectors_skipped += (max_sector - sector_nr);
 	chunks_skipped ++;
 	sector_nr = max_sector;
 	goto skipped;
-	}
 }
 
 static int run(mddev_t *mddev)
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 40ebde5..b019869 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -51,6 +51,10 @@
 	depends on DVB_CORE && PCI && I2C
 source "drivers/media/dvb/dm1105/Kconfig"
 
+comment "Supported FireWire (IEEE 1394) Adapters"
+	depends on DVB_CORE && IEEE1394
+source "drivers/media/dvb/firewire/Kconfig"
+
 comment "Supported DVB Frontends"
 	depends on DVB_CORE
 source "drivers/media/dvb/frontends/Kconfig"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index f91e9eb..6092a5b 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -3,3 +3,5 @@
 #
 
 obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/
+
+obj-$(CONFIG_DVB_FIREDTV)	+= firewire/
diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
index b386cc6..451974b 100644
--- a/drivers/media/dvb/b2c2/flexcop-hw-filter.c
+++ b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
@@ -192,6 +192,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(flexcop_pid_feed_control);
 
 void flexcop_hw_filter_init(struct flexcop_device *fc)
 {
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
index 5b30dfc..76e37fd 100644
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -13,9 +13,9 @@
 module_param(enable_pid_filtering, int, 0444);
 MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1");
 
-static int irq_chk_intv;
+static int irq_chk_intv = 100;
 module_param(irq_chk_intv, int, 0644);
-MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ watchdog (currently just debugging).");
+MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog.");
 
 #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
 #define dprintk(level,args...) \
@@ -34,7 +34,9 @@
 
 static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS);
+MODULE_PARM_DESC(debug,
+	"set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))."
+	 DEBSTATUS);
 
 #define DRIVER_VERSION "0.1"
 #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
@@ -58,6 +60,8 @@
 	int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */
 	u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */
 	int count;
+	int count_prev;
+	int stream_problem;
 
 	spinlock_t irq_lock;
 
@@ -103,18 +107,32 @@
 		container_of(work, struct flexcop_pci, irq_check_work.work);
 	struct flexcop_device *fc = fc_pci->fc_dev;
 
-	flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+	if (fc->feedcount) {
 
-	flexcop_dump_reg(fc_pci->fc_dev,dma1_000,4);
+		if (fc_pci->count == fc_pci->count_prev) {
+			deb_chk("no IRQ since the last check\n");
+			if (fc_pci->stream_problem++ == 3) {
+				struct dvb_demux_feed *feed;
 
-	if (v.sram_dest_reg_714.net_ovflow_error)
-		deb_chk("sram net_ovflow_error\n");
-	if (v.sram_dest_reg_714.media_ovflow_error)
-		deb_chk("sram media_ovflow_error\n");
-	if (v.sram_dest_reg_714.cai_ovflow_error)
-		deb_chk("sram cai_ovflow_error\n");
-	if (v.sram_dest_reg_714.cai_ovflow_error)
-		deb_chk("sram cai_ovflow_error\n");
+				spin_lock_irq(&fc->demux.lock);
+				list_for_each_entry(feed, &fc->demux.feed_list,
+					list_head) {
+					flexcop_pid_feed_control(fc, feed, 0);
+				}
+
+				list_for_each_entry(feed, &fc->demux.feed_list,
+					list_head) {
+					flexcop_pid_feed_control(fc, feed, 1);
+				}
+				spin_unlock_irq(&fc->demux.lock);
+
+				fc_pci->stream_problem = 0;
+			}
+		} else {
+			fc_pci->stream_problem = 0;
+			fc_pci->count_prev = fc_pci->count;
+		}
+	}
 
 	schedule_delayed_work(&fc_pci->irq_check_work,
 			msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
@@ -216,16 +234,12 @@
 		flexcop_dma_control_timer_irq(fc,FC_DMA_1,1);
 		deb_irq("IRQ enabled\n");
 
+		fc_pci->count_prev = fc_pci->count;
+
 //		fc_pci->active_dma1_addr = 0;
 //		flexcop_dma_control_size_irq(fc,FC_DMA_1,1);
 
-		if (irq_chk_intv > 0)
-			schedule_delayed_work(&fc_pci->irq_check_work,
-					msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
 	} else {
-		if (irq_chk_intv > 0)
-			cancel_delayed_work(&fc_pci->irq_check_work);
-
 		flexcop_dma_control_timer_irq(fc,FC_DMA_1,0);
 		deb_irq("IRQ disabled\n");
 
@@ -299,8 +313,6 @@
 					IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0)
 		goto err_pci_iounmap;
 
-
-
 	fc_pci->init_state |= FC_PCI_INIT;
 	return ret;
 
@@ -375,6 +387,10 @@
 
 	INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work);
 
+		if (irq_chk_intv > 0)
+			schedule_delayed_work(&fc_pci->irq_check_work,
+		msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
+
 	return ret;
 
 err_fc_exit:
@@ -393,6 +409,9 @@
 {
 	struct flexcop_pci *fc_pci = pci_get_drvdata(pdev);
 
+	if (irq_chk_intv > 0)
+		cancel_delayed_work(&fc_pci->irq_check_work);
+
 	flexcop_pci_dma_exit(fc_pci);
 	flexcop_device_exit(fc_pci->fc_dev);
 	flexcop_pci_exit(fc_pci);
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
index 676413a..9106895 100644
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -212,8 +212,7 @@
 	v210.sw_reset_210.Block_reset_enable = 0xb2;
 
 	fc->write_ibi_reg(fc,sw_reset_210,v210);
-	msleep(1);
-
+	udelay(1000);
 	fc->write_ibi_reg(fc,ctrl_208,v208_save);
 }
 
diff --git a/drivers/media/dvb/firewire/Kconfig b/drivers/media/dvb/firewire/Kconfig
new file mode 100644
index 0000000..6902825
--- /dev/null
+++ b/drivers/media/dvb/firewire/Kconfig
@@ -0,0 +1,22 @@
+config DVB_FIREDTV
+	tristate "FireDTV and FloppyDTV"
+	depends on DVB_CORE && IEEE1394
+	help
+	  Support for DVB receivers from Digital Everywhere
+	  which are connected via IEEE 1394 (FireWire).
+
+	  These devices don't have an MPEG decoder built in,
+	  so you need an external software decoder to watch TV.
+
+	  To compile this driver as a module, say M here:
+	  the module will be called firedtv.
+
+if DVB_FIREDTV
+
+config DVB_FIREDTV_IEEE1394
+	def_bool IEEE1394
+
+config DVB_FIREDTV_INPUT
+	def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
+
+endif # DVB_FIREDTV
diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/dvb/firewire/Makefile
new file mode 100644
index 0000000..2034695
--- /dev/null
+++ b/drivers/media/dvb/firewire/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
+
+firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
+firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
+firedtv-$(CONFIG_DVB_FIREDTV_INPUT)    += firedtv-rc.o
+
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c
new file mode 100644
index 0000000..4e20765
--- /dev/null
+++ b/drivers/media/dvb/firewire/firedtv-1394.c
@@ -0,0 +1,285 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	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/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <dma.h>
+#include <csr1212.h>
+#include <highlevel.h>
+#include <hosts.h>
+#include <ieee1394.h>
+#include <iso.h>
+#include <nodemgr.h>
+
+#include "firedtv.h"
+
+static LIST_HEAD(node_list);
+static DEFINE_SPINLOCK(node_list_lock);
+
+#define FIREWIRE_HEADER_SIZE	4
+#define CIP_HEADER_SIZE		8
+
+static void rawiso_activity_cb(struct hpsb_iso *iso)
+{
+	struct firedtv *f, *fdtv = NULL;
+	unsigned int i, num, packet;
+	unsigned char *buf;
+	unsigned long flags;
+	int count;
+
+	spin_lock_irqsave(&node_list_lock, flags);
+	list_for_each_entry(f, &node_list, list)
+		if (f->backend_data == iso) {
+			fdtv = f;
+			break;
+		}
+	spin_unlock_irqrestore(&node_list_lock, flags);
+
+	packet = iso->first_packet;
+	num = hpsb_iso_n_ready(iso);
+
+	if (!fdtv) {
+		dev_err(fdtv->device, "received at unknown iso channel\n");
+		goto out;
+	}
+
+	for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) {
+		buf = dma_region_i(&iso->data_buf, unsigned char,
+			iso->infos[packet].offset + CIP_HEADER_SIZE);
+		count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
+			(188 + FIREWIRE_HEADER_SIZE);
+
+		/* ignore empty packet */
+		if (iso->infos[packet].len <= CIP_HEADER_SIZE)
+			continue;
+
+		while (count--) {
+			if (buf[FIREWIRE_HEADER_SIZE] == 0x47)
+				dvb_dmx_swfilter_packets(&fdtv->demux,
+						&buf[FIREWIRE_HEADER_SIZE], 1);
+			else
+				dev_err(fdtv->device,
+					"skipping invalid packet\n");
+			buf += 188 + FIREWIRE_HEADER_SIZE;
+		}
+	}
+out:
+	hpsb_iso_recv_release_packets(iso, num);
+}
+
+static inline struct node_entry *node_of(struct firedtv *fdtv)
+{
+	return container_of(fdtv->device, struct unit_directory, device)->ne;
+}
+
+static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg)
+{
+	return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data,
+			      (__force quadlet_t)arg);
+}
+
+static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+{
+	return hpsb_node_read(node_of(fdtv), addr, data, len);
+}
+
+static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+{
+	return hpsb_node_write(node_of(fdtv), addr, data, len);
+}
+
+#define FDTV_ISO_BUFFER_PACKETS 256
+#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
+
+static int start_iso(struct firedtv *fdtv)
+{
+	struct hpsb_iso *iso_handle;
+	int ret;
+
+	iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host,
+				FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS,
+				fdtv->isochannel, HPSB_ISO_DMA_DEFAULT,
+				-1, /* stat.config.irq_interval */
+				rawiso_activity_cb);
+	if (iso_handle == NULL) {
+		dev_err(fdtv->device, "cannot initialize iso receive\n");
+		return -ENOMEM;
+	}
+	fdtv->backend_data = iso_handle;
+
+	ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0);
+	if (ret != 0) {
+		dev_err(fdtv->device, "cannot start iso receive\n");
+		hpsb_iso_shutdown(iso_handle);
+		fdtv->backend_data = NULL;
+	}
+	return ret;
+}
+
+static void stop_iso(struct firedtv *fdtv)
+{
+	struct hpsb_iso *iso_handle = fdtv->backend_data;
+
+	if (iso_handle != NULL) {
+		hpsb_iso_stop(iso_handle);
+		hpsb_iso_shutdown(iso_handle);
+	}
+	fdtv->backend_data = NULL;
+}
+
+static const struct firedtv_backend fdtv_1394_backend = {
+	.lock		= node_lock,
+	.read		= node_read,
+	.write		= node_write,
+	.start_iso	= start_iso,
+	.stop_iso	= stop_iso,
+};
+
+static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
+			int cts, u8 *data, size_t length)
+{
+	struct firedtv *f, *fdtv = NULL;
+	unsigned long flags;
+	int su;
+
+	if (length == 0 || (data[0] & 0xf0) != 0)
+		return;
+
+	su = data[1] & 0x7;
+
+	spin_lock_irqsave(&node_list_lock, flags);
+	list_for_each_entry(f, &node_list, list)
+		if (node_of(f)->host == host &&
+		    node_of(f)->nodeid == nodeid &&
+		    (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
+			fdtv = f;
+			break;
+		}
+	spin_unlock_irqrestore(&node_list_lock, flags);
+
+	if (fdtv)
+		avc_recv(fdtv, data, length);
+}
+
+static int node_probe(struct device *dev)
+{
+	struct unit_directory *ud =
+			container_of(dev, struct unit_directory, device);
+	struct firedtv *fdtv;
+	int kv_len, err;
+	void *kv_str;
+
+	kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t);
+	kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
+
+	fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
+	if (!fdtv)
+		return -ENOMEM;
+
+	/*
+	 * Work around a bug in udev's path_id script:  Use the fw-host's dev
+	 * instead of the unit directory's dev as parent of the input device.
+	 */
+	err = fdtv_register_rc(fdtv, dev->parent->parent);
+	if (err)
+		goto fail_free;
+
+	spin_lock_irq(&node_list_lock);
+	list_add_tail(&fdtv->list, &node_list);
+	spin_unlock_irq(&node_list_lock);
+
+	err = avc_identify_subunit(fdtv);
+	if (err)
+		goto fail;
+
+	err = fdtv_dvb_register(fdtv);
+	if (err)
+		goto fail;
+
+	avc_register_remote_control(fdtv);
+	return 0;
+fail:
+	spin_lock_irq(&node_list_lock);
+	list_del(&fdtv->list);
+	spin_unlock_irq(&node_list_lock);
+	fdtv_unregister_rc(fdtv);
+fail_free:
+	kfree(fdtv);
+	return err;
+}
+
+static int node_remove(struct device *dev)
+{
+	struct firedtv *fdtv = dev->driver_data;
+
+	fdtv_dvb_unregister(fdtv);
+
+	spin_lock_irq(&node_list_lock);
+	list_del(&fdtv->list);
+	spin_unlock_irq(&node_list_lock);
+
+	cancel_work_sync(&fdtv->remote_ctrl_work);
+	fdtv_unregister_rc(fdtv);
+
+	kfree(fdtv);
+	return 0;
+}
+
+static int node_update(struct unit_directory *ud)
+{
+	struct firedtv *fdtv = ud->device.driver_data;
+
+	if (fdtv->isochannel >= 0)
+		cmp_establish_pp_connection(fdtv, fdtv->subunit,
+					    fdtv->isochannel);
+	return 0;
+}
+
+static struct hpsb_protocol_driver fdtv_driver = {
+	.name		= "firedtv",
+	.update		= node_update,
+	.driver         = {
+		.probe  = node_probe,
+		.remove = node_remove,
+	},
+};
+
+static struct hpsb_highlevel fdtv_highlevel = {
+	.name		= "firedtv",
+	.fcp_request	= fcp_request,
+};
+
+int __init fdtv_1394_init(struct ieee1394_device_id id_table[])
+{
+	int ret;
+
+	hpsb_register_highlevel(&fdtv_highlevel);
+	fdtv_driver.id_table = id_table;
+	ret = hpsb_register_protocol(&fdtv_driver);
+	if (ret) {
+		printk(KERN_ERR "firedtv: failed to register protocol\n");
+		hpsb_unregister_highlevel(&fdtv_highlevel);
+	}
+	return ret;
+}
+
+void __exit fdtv_1394_exit(void)
+{
+	hpsb_unregister_protocol(&fdtv_driver);
+	hpsb_unregister_highlevel(&fdtv_highlevel);
+}
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
new file mode 100644
index 0000000..b55d9cc
--- /dev/null
+++ b/drivers/media/dvb/firewire/firedtv-avc.c
@@ -0,0 +1,1315 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	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/bug.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include "firedtv.h"
+
+#define FCP_COMMAND_REGISTER		0xfffff0000b00ULL
+
+#define AVC_CTYPE_CONTROL		0x0
+#define AVC_CTYPE_STATUS		0x1
+#define AVC_CTYPE_NOTIFY		0x3
+
+#define AVC_RESPONSE_ACCEPTED		0x9
+#define AVC_RESPONSE_STABLE		0xc
+#define AVC_RESPONSE_CHANGED		0xd
+#define AVC_RESPONSE_INTERIM		0xf
+
+#define AVC_SUBUNIT_TYPE_TUNER		(0x05 << 3)
+#define AVC_SUBUNIT_TYPE_UNIT		(0x1f << 3)
+
+#define AVC_OPCODE_VENDOR		0x00
+#define AVC_OPCODE_READ_DESCRIPTOR	0x09
+#define AVC_OPCODE_DSIT			0xc8
+#define AVC_OPCODE_DSD			0xcb
+
+#define DESCRIPTOR_TUNER_STATUS 	0x80
+#define DESCRIPTOR_SUBUNIT_IDENTIFIER	0x00
+
+#define SFE_VENDOR_DE_COMPANYID_0	0x00 /* OUI of Digital Everywhere */
+#define SFE_VENDOR_DE_COMPANYID_1	0x12
+#define SFE_VENDOR_DE_COMPANYID_2	0x87
+
+#define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
+#define SFE_VENDOR_OPCODE_LNB_CONTROL		0x52
+#define SFE_VENDOR_OPCODE_TUNE_QPSK		0x58 /* for DVB-S */
+
+#define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION	0x00
+#define SFE_VENDOR_OPCODE_HOST2CA		0x56
+#define SFE_VENDOR_OPCODE_CA2HOST		0x57
+#define SFE_VENDOR_OPCODE_CISTATUS		0x59
+#define SFE_VENDOR_OPCODE_TUNE_QPSK2		0x60 /* for DVB-S2 */
+
+#define SFE_VENDOR_TAG_CA_RESET			0x00
+#define SFE_VENDOR_TAG_CA_APPLICATION_INFO	0x01
+#define SFE_VENDOR_TAG_CA_PMT			0x02
+#define SFE_VENDOR_TAG_CA_DATE_TIME		0x04
+#define SFE_VENDOR_TAG_CA_MMI			0x05
+#define SFE_VENDOR_TAG_CA_ENTER_MENU		0x07
+
+#define EN50221_LIST_MANAGEMENT_ONLY	0x03
+#define EN50221_TAG_APP_INFO		0x9f8021
+#define EN50221_TAG_CA_INFO		0x9f8031
+
+struct avc_command_frame {
+	int length;
+	u8 ctype;
+	u8 subunit;
+	u8 opcode;
+	u8 operand[509];
+};
+
+struct avc_response_frame {
+	int length;
+	u8 response;
+	u8 subunit;
+	u8 opcode;
+	u8 operand[509];
+};
+
+#define AVC_DEBUG_FCP_SUBACTIONS	1
+#define AVC_DEBUG_FCP_PAYLOADS		2
+
+static int avc_debug;
+module_param_named(debug, avc_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
+	", FCP subactions = "	__stringify(AVC_DEBUG_FCP_SUBACTIONS)
+	", FCP payloads = "	__stringify(AVC_DEBUG_FCP_PAYLOADS)
+	", or all = -1)");
+
+static const char *debug_fcp_ctype(unsigned int ctype)
+{
+	static const char *ctypes[] = {
+		[0x0] = "CONTROL",		[0x1] = "STATUS",
+		[0x2] = "SPECIFIC INQUIRY",	[0x3] = "NOTIFY",
+		[0x4] = "GENERAL INQUIRY",	[0x8] = "NOT IMPLEMENTED",
+		[0x9] = "ACCEPTED",		[0xa] = "REJECTED",
+		[0xb] = "IN TRANSITION",	[0xc] = "IMPLEMENTED/STABLE",
+		[0xd] = "CHANGED",		[0xf] = "INTERIM",
+	};
+	const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL;
+
+	return ret ? ret : "?";
+}
+
+static const char *debug_fcp_opcode(unsigned int opcode,
+				    const u8 *data, size_t length)
+{
+	switch (opcode) {
+	case AVC_OPCODE_VENDOR:			break;
+	case AVC_OPCODE_READ_DESCRIPTOR:	return "ReadDescriptor";
+	case AVC_OPCODE_DSIT:			return "DirectSelectInfo.Type";
+	case AVC_OPCODE_DSD:			return "DirectSelectData";
+	default:				return "?";
+	}
+
+	if (length < 7 ||
+	    data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
+	    data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
+	    data[5] != SFE_VENDOR_DE_COMPANYID_2)
+		return "Vendor";
+
+	switch (data[6]) {
+	case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL:	return "RegisterRC";
+	case SFE_VENDOR_OPCODE_LNB_CONTROL:		return "LNBControl";
+	case SFE_VENDOR_OPCODE_TUNE_QPSK:		return "TuneQPSK";
+	case SFE_VENDOR_OPCODE_HOST2CA:			return "Host2CA";
+	case SFE_VENDOR_OPCODE_CA2HOST:			return "CA2Host";
+	}
+	return "Vendor";
+}
+
+static void debug_fcp(const u8 *data, size_t length)
+{
+	unsigned int subunit_type, subunit_id, op;
+	const char *prefix = data[0] > 7 ? "FCP <- " : "FCP -> ";
+
+	if (avc_debug & AVC_DEBUG_FCP_SUBACTIONS) {
+		subunit_type = data[1] >> 3;
+		subunit_id = data[1] & 7;
+		op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
+		printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
+		       prefix, subunit_type, subunit_id, length,
+		       debug_fcp_ctype(data[0]),
+		       debug_fcp_opcode(op, data, length));
+	}
+
+	if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
+		print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE, 16, 1,
+			       data, length, false);
+}
+
+static int __avc_write(struct firedtv *fdtv,
+		const struct avc_command_frame *c, struct avc_response_frame *r)
+{
+	int err, retry;
+
+	if (r)
+		fdtv->avc_reply_received = false;
+
+	for (retry = 0; retry < 6; retry++) {
+		if (unlikely(avc_debug))
+			debug_fcp(&c->ctype, c->length);
+
+		err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
+					   (void *)&c->ctype, c->length);
+		if (err) {
+			fdtv->avc_reply_received = true;
+			dev_err(fdtv->device, "FCP command write failed\n");
+			return err;
+		}
+
+		if (!r)
+			return 0;
+
+		/*
+		 * AV/C specs say that answers should be sent within 150 ms.
+		 * Time out after 200 ms.
+		 */
+		if (wait_event_timeout(fdtv->avc_wait,
+				       fdtv->avc_reply_received,
+				       msecs_to_jiffies(200)) != 0) {
+			r->length = fdtv->response_length;
+			memcpy(&r->response, fdtv->response, r->length);
+
+			return 0;
+		}
+	}
+	dev_err(fdtv->device, "FCP response timed out\n");
+	return -ETIMEDOUT;
+}
+
+static int avc_write(struct firedtv *fdtv,
+		const struct avc_command_frame *c, struct avc_response_frame *r)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
+
+	ret = __avc_write(fdtv, c, r);
+
+	mutex_unlock(&fdtv->avc_mutex);
+	return ret;
+}
+
+int avc_recv(struct firedtv *fdtv, void *data, size_t length)
+{
+	struct avc_response_frame *r =
+			data - offsetof(struct avc_response_frame, response);
+
+	if (unlikely(avc_debug))
+		debug_fcp(data, length);
+
+	if (length >= 8 &&
+	    r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
+	    r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
+	    r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
+	    r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) {
+		if (r->response == AVC_RESPONSE_CHANGED) {
+			fdtv_handle_rc(fdtv,
+			    r->operand[4] << 8 | r->operand[5]);
+			schedule_work(&fdtv->remote_ctrl_work);
+		} else if (r->response != AVC_RESPONSE_INTERIM) {
+			dev_info(fdtv->device,
+				 "remote control result = %d\n", r->response);
+		}
+		return 0;
+	}
+
+	if (fdtv->avc_reply_received) {
+		dev_err(fdtv->device, "out-of-order AVC response, ignored\n");
+		return -EIO;
+	}
+
+	memcpy(fdtv->response, data, length);
+	fdtv->response_length = length;
+
+	fdtv->avc_reply_received = true;
+	wake_up(&fdtv->avc_wait);
+
+	return 0;
+}
+
+/*
+ * tuning command for setting the relative LNB frequency
+ * (not supported by the AVC standard)
+ */
+static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
+			       struct dvb_frontend_parameters *params,
+			       struct avc_command_frame *c)
+{
+	c->opcode = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
+
+	c->operand[4] = (params->frequency >> 24) & 0xff;
+	c->operand[5] = (params->frequency >> 16) & 0xff;
+	c->operand[6] = (params->frequency >> 8) & 0xff;
+	c->operand[7] = params->frequency & 0xff;
+
+	c->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff;
+	c->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff;
+
+	switch (params->u.qpsk.fec_inner) {
+	case FEC_1_2:	c->operand[10] = 0x1; break;
+	case FEC_2_3:	c->operand[10] = 0x2; break;
+	case FEC_3_4:	c->operand[10] = 0x3; break;
+	case FEC_5_6:	c->operand[10] = 0x4; break;
+	case FEC_7_8:	c->operand[10] = 0x5; break;
+	case FEC_4_5:
+	case FEC_8_9:
+	case FEC_AUTO:
+	default:	c->operand[10] = 0x0;
+	}
+
+	if (fdtv->voltage == 0xff)
+		c->operand[11] = 0xff;
+	else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
+		c->operand[11] = 0;
+	else
+		c->operand[11] = 1;
+
+	if (fdtv->tone == 0xff)
+		c->operand[12] = 0xff;
+	else if (fdtv->tone == SEC_TONE_ON) /* band */
+		c->operand[12] = 1;
+	else
+		c->operand[12] = 0;
+
+	if (fdtv->type == FIREDTV_DVB_S2) {
+		c->operand[13] = 0x1;
+		c->operand[14] = 0xff;
+		c->operand[15] = 0xff;
+		c->length = 20;
+	} else {
+		c->length = 16;
+	}
+}
+
+static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params,
+				struct avc_command_frame *c)
+{
+	c->opcode = AVC_OPCODE_DSD;
+
+	c->operand[0] = 0;    /* source plug */
+	c->operand[1] = 0xd2; /* subfunction replace */
+	c->operand[2] = 0x20; /* system id = DVB */
+	c->operand[3] = 0x00; /* antenna number */
+	c->operand[4] = 0x11; /* system_specific_multiplex selection_length */
+
+	/* multiplex_valid_flags, high byte */
+	c->operand[5] =   0 << 7 /* reserved */
+			| 0 << 6 /* Polarisation */
+			| 0 << 5 /* Orbital_Pos */
+			| 1 << 4 /* Frequency */
+			| 1 << 3 /* Symbol_Rate */
+			| 0 << 2 /* FEC_outer */
+			| (params->u.qam.fec_inner  != FEC_AUTO ? 1 << 1 : 0)
+			| (params->u.qam.modulation != QAM_AUTO ? 1 << 0 : 0);
+
+	/* multiplex_valid_flags, low byte */
+	c->operand[6] =   0 << 7 /* NetworkID */
+			| 0 << 0 /* reserved */ ;
+
+	c->operand[7]  = 0x00;
+	c->operand[8]  = 0x00;
+	c->operand[9]  = 0x00;
+	c->operand[10] = 0x00;
+
+	c->operand[11] = (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6);
+	c->operand[12] = ((params->frequency / 4000) >> 8) & 0xff;
+	c->operand[13] = (params->frequency / 4000) & 0xff;
+	c->operand[14] = ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff;
+	c->operand[15] = ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff;
+	c->operand[16] = ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0;
+	c->operand[17] = 0x00;
+
+	switch (params->u.qpsk.fec_inner) {
+	case FEC_1_2:	c->operand[18] = 0x1; break;
+	case FEC_2_3:	c->operand[18] = 0x2; break;
+	case FEC_3_4:	c->operand[18] = 0x3; break;
+	case FEC_5_6:	c->operand[18] = 0x4; break;
+	case FEC_7_8:	c->operand[18] = 0x5; break;
+	case FEC_8_9:	c->operand[18] = 0x6; break;
+	case FEC_4_5:	c->operand[18] = 0x8; break;
+	case FEC_AUTO:
+	default:	c->operand[18] = 0x0;
+	}
+
+	switch (params->u.qam.modulation) {
+	case QAM_16:	c->operand[19] = 0x08; break;
+	case QAM_32:	c->operand[19] = 0x10; break;
+	case QAM_64:	c->operand[19] = 0x18; break;
+	case QAM_128:	c->operand[19] = 0x20; break;
+	case QAM_256:	c->operand[19] = 0x28; break;
+	case QAM_AUTO:
+	default:	c->operand[19] = 0x00;
+	}
+
+	c->operand[20] = 0x00;
+	c->operand[21] = 0x00;
+	/* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
+	c->operand[22] = 0x00;
+
+	c->length = 28;
+}
+
+static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params,
+				struct avc_command_frame *c)
+{
+	struct dvb_ofdm_parameters *ofdm = &params->u.ofdm;
+
+	c->opcode = AVC_OPCODE_DSD;
+
+	c->operand[0] = 0;    /* source plug */
+	c->operand[1] = 0xd2; /* subfunction replace */
+	c->operand[2] = 0x20; /* system id = DVB */
+	c->operand[3] = 0x00; /* antenna number */
+	c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */
+
+	/* multiplex_valid_flags, high byte */
+	c->operand[5] =
+	      0 << 7 /* reserved */
+	    | 1 << 6 /* CenterFrequency */
+	    | (ofdm->bandwidth      != BANDWIDTH_AUTO        ? 1 << 5 : 0)
+	    | (ofdm->constellation  != QAM_AUTO              ? 1 << 4 : 0)
+	    | (ofdm->hierarchy_information != HIERARCHY_AUTO ? 1 << 3 : 0)
+	    | (ofdm->code_rate_HP   != FEC_AUTO              ? 1 << 2 : 0)
+	    | (ofdm->code_rate_LP   != FEC_AUTO              ? 1 << 1 : 0)
+	    | (ofdm->guard_interval != GUARD_INTERVAL_AUTO   ? 1 << 0 : 0);
+
+	/* multiplex_valid_flags, low byte */
+	c->operand[6] =
+	      0 << 7 /* NetworkID */
+	    | (ofdm->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
+	    | 0 << 5 /* OtherFrequencyFlag */
+	    | 0 << 0 /* reserved */ ;
+
+	c->operand[7]  = 0x0;
+	c->operand[8]  = (params->frequency / 10) >> 24;
+	c->operand[9]  = ((params->frequency / 10) >> 16) & 0xff;
+	c->operand[10] = ((params->frequency / 10) >>  8) & 0xff;
+	c->operand[11] = (params->frequency / 10) & 0xff;
+
+	switch (ofdm->bandwidth) {
+	case BANDWIDTH_7_MHZ:	c->operand[12] = 0x20; break;
+	case BANDWIDTH_8_MHZ:
+	case BANDWIDTH_6_MHZ:	/* not defined by AVC spec */
+	case BANDWIDTH_AUTO:
+	default:		c->operand[12] = 0x00;
+	}
+
+	switch (ofdm->constellation) {
+	case QAM_16:	c->operand[13] = 1 << 6; break;
+	case QAM_64:	c->operand[13] = 2 << 6; break;
+	case QPSK:
+	default:	c->operand[13] = 0x00;
+	}
+
+	switch (ofdm->hierarchy_information) {
+	case HIERARCHY_1:	c->operand[13] |= 1 << 3; break;
+	case HIERARCHY_2:	c->operand[13] |= 2 << 3; break;
+	case HIERARCHY_4:	c->operand[13] |= 3 << 3; break;
+	case HIERARCHY_AUTO:
+	case HIERARCHY_NONE:
+	default:		break;
+	}
+
+	switch (ofdm->code_rate_HP) {
+	case FEC_2_3:	c->operand[13] |= 1; break;
+	case FEC_3_4:	c->operand[13] |= 2; break;
+	case FEC_5_6:	c->operand[13] |= 3; break;
+	case FEC_7_8:	c->operand[13] |= 4; break;
+	case FEC_1_2:
+	default:	break;
+	}
+
+	switch (ofdm->code_rate_LP) {
+	case FEC_2_3:	c->operand[14] = 1 << 5; break;
+	case FEC_3_4:	c->operand[14] = 2 << 5; break;
+	case FEC_5_6:	c->operand[14] = 3 << 5; break;
+	case FEC_7_8:	c->operand[14] = 4 << 5; break;
+	case FEC_1_2:
+	default:	c->operand[14] = 0x00; break;
+	}
+
+	switch (ofdm->guard_interval) {
+	case GUARD_INTERVAL_1_16:	c->operand[14] |= 1 << 3; break;
+	case GUARD_INTERVAL_1_8:	c->operand[14] |= 2 << 3; break;
+	case GUARD_INTERVAL_1_4:	c->operand[14] |= 3 << 3; break;
+	case GUARD_INTERVAL_1_32:
+	case GUARD_INTERVAL_AUTO:
+	default:			break;
+	}
+
+	switch (ofdm->transmission_mode) {
+	case TRANSMISSION_MODE_8K:	c->operand[14] |= 1 << 1; break;
+	case TRANSMISSION_MODE_2K:
+	case TRANSMISSION_MODE_AUTO:
+	default:			break;
+	}
+
+	c->operand[15] = 0x00; /* network_ID[0] */
+	c->operand[16] = 0x00; /* network_ID[1] */
+	/* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */
+	c->operand[17] = 0x00;
+
+	c->length = 24;
+}
+
+int avc_tuner_dsd(struct firedtv *fdtv,
+		  struct dvb_frontend_parameters *params)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+
+	switch (fdtv->type) {
+	case FIREDTV_DVB_S:
+	case FIREDTV_DVB_S2: avc_tuner_tuneqpsk(fdtv, params, c); break;
+	case FIREDTV_DVB_C: avc_tuner_dsd_dvb_c(params, c); break;
+	case FIREDTV_DVB_T: avc_tuner_dsd_dvb_t(params, c); break;
+	default:
+		BUG();
+	}
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	msleep(500);
+#if 0
+	/* FIXME: */
+	/* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */
+	if (status)
+		*status = r->operand[2];
+#endif
+	return 0;
+}
+
+int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+	int pos, k;
+
+	if (pidc > 16 && pidc != 0xff)
+		return -EINVAL;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_DSD;
+
+	c->operand[0] = 0;	/* source plug */
+	c->operand[1] = 0xd2;	/* subfunction replace */
+	c->operand[2] = 0x20;	/* system id = DVB */
+	c->operand[3] = 0x00;	/* antenna number */
+	c->operand[4] = 0x00;	/* system_specific_multiplex selection_length */
+	c->operand[5] = pidc;	/* Nr_of_dsd_sel_specs */
+
+	pos = 6;
+	if (pidc != 0xff)
+		for (k = 0; k < pidc; k++) {
+			c->operand[pos++] = 0x13; /* flowfunction relay */
+			c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
+			c->operand[pos++] = (pid[k] >> 8) & 0x1f;
+			c->operand[pos++] = pid[k] & 0xff;
+			c->operand[pos++] = 0x00; /* tableID */
+			c->operand[pos++] = 0x00; /* filter_length */
+		}
+
+	c->length = ALIGN(3 + pos, 4);
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	msleep(50);
+	return 0;
+}
+
+int avc_tuner_get_ts(struct firedtv *fdtv)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+	int sl;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_DSIT;
+
+	sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11;
+
+	c->operand[0] = 0;	/* source plug */
+	c->operand[1] = 0xd2;	/* subfunction replace */
+	c->operand[2] = 0xff;	/* status */
+	c->operand[3] = 0x20;	/* system id = DVB */
+	c->operand[4] = 0x00;	/* antenna number */
+	c->operand[5] = 0x0; 	/* system_specific_search_flags */
+	c->operand[6] = sl;	/* system_specific_multiplex selection_length */
+	c->operand[7] = 0x00;	/* valid_flags [0] */
+	c->operand[8] = 0x00;	/* valid_flags [1] */
+	c->operand[7 + sl] = 0x00; /* nr_of_dsit_sel_specs (always 0) */
+
+	c->length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	msleep(250);
+	return 0;
+}
+
+int avc_identify_subunit(struct firedtv *fdtv)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
+
+	c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER;
+	c->operand[1] = 0xff;
+	c->operand[2] = 0x00;
+	c->operand[3] = 0x00; /* length highbyte */
+	c->operand[4] = 0x08; /* length lowbyte  */
+	c->operand[5] = 0x00; /* offset highbyte */
+	c->operand[6] = 0x0d; /* offset lowbyte  */
+
+	c->length = 12;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	if ((r->response != AVC_RESPONSE_STABLE &&
+	     r->response != AVC_RESPONSE_ACCEPTED) ||
+	    (r->operand[3] << 8) + r->operand[4] != 8) {
+		dev_err(fdtv->device, "cannot read subunit identifier\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+#define SIZEOF_ANTENNA_INPUT_INFO 22
+
+int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer;
+	int length;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
+
+	c->operand[0] = DESCRIPTOR_TUNER_STATUS;
+	c->operand[1] = 0xff;	/* read_result_status */
+	c->operand[2] = 0x00;	/* reserved */
+	c->operand[3] = 0;	/* SIZEOF_ANTENNA_INPUT_INFO >> 8; */
+	c->operand[4] = 0;	/* SIZEOF_ANTENNA_INPUT_INFO & 0xff; */
+	c->operand[5] = 0x00;
+	c->operand[6] = 0x00;
+
+	c->length = 12;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	if (r->response != AVC_RESPONSE_STABLE &&
+	    r->response != AVC_RESPONSE_ACCEPTED) {
+		dev_err(fdtv->device, "cannot read tuner status\n");
+		return -EINVAL;
+	}
+
+	length = r->operand[9];
+	if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
+		dev_err(fdtv->device, "got invalid tuner status\n");
+		return -EINVAL;
+	}
+
+	stat->active_system		= r->operand[10];
+	stat->searching			= r->operand[11] >> 7 & 1;
+	stat->moving			= r->operand[11] >> 6 & 1;
+	stat->no_rf			= r->operand[11] >> 5 & 1;
+	stat->input			= r->operand[12] >> 7 & 1;
+	stat->selected_antenna		= r->operand[12] & 0x7f;
+	stat->ber			= r->operand[13] << 24 |
+					  r->operand[14] << 16 |
+					  r->operand[15] << 8 |
+					  r->operand[16];
+	stat->signal_strength		= r->operand[17];
+	stat->raster_frequency		= r->operand[18] >> 6 & 2;
+	stat->rf_frequency		= (r->operand[18] & 0x3f) << 16 |
+					  r->operand[19] << 8 |
+					  r->operand[20];
+	stat->man_dep_info_length	= r->operand[21];
+	stat->front_end_error		= r->operand[22] >> 4 & 1;
+	stat->antenna_error		= r->operand[22] >> 3 & 1;
+	stat->front_end_power_status	= r->operand[22] >> 1 & 1;
+	stat->power_supply		= r->operand[22] & 1;
+	stat->carrier_noise_ratio	= r->operand[23] << 8 |
+					  r->operand[24];
+	stat->power_supply_voltage	= r->operand[27];
+	stat->antenna_voltage		= r->operand[28];
+	stat->firewire_bus_voltage	= r->operand[29];
+	stat->ca_mmi			= r->operand[30] & 1;
+	stat->ca_pmt_reply		= r->operand[31] >> 7 & 1;
+	stat->ca_date_time_request	= r->operand[31] >> 6 & 1;
+	stat->ca_application_info	= r->operand[31] >> 5 & 1;
+	stat->ca_module_present_status	= r->operand[31] >> 4 & 1;
+	stat->ca_dvb_flag		= r->operand[31] >> 3 & 1;
+	stat->ca_error_flag		= r->operand[31] >> 2 & 1;
+	stat->ca_initialization_status	= r->operand[31] >> 1 & 1;
+
+	return 0;
+}
+
+int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
+		    char conttone, char nrdiseq,
+		    struct dvb_diseqc_master_cmd *diseqcmd)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer;
+	int i, j, k;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
+
+	c->operand[4] = voltage;
+	c->operand[5] = nrdiseq;
+
+	i = 6;
+
+	for (j = 0; j < nrdiseq; j++) {
+		c->operand[i++] = diseqcmd[j].msg_len;
+
+		for (k = 0; k < diseqcmd[j].msg_len; k++)
+			c->operand[i++] = diseqcmd[j].msg[k];
+	}
+
+	c->operand[i++] = burst;
+	c->operand[i++] = conttone;
+
+	c->length = ALIGN(3 + i, 4);
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	if (r->response != AVC_RESPONSE_ACCEPTED) {
+		dev_err(fdtv->device, "LNB control failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int avc_register_remote_control(struct firedtv *fdtv)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_NOTIFY;
+	c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
+
+	c->length = 8;
+
+	return avc_write(fdtv, c, NULL);
+}
+
+void avc_remote_ctrl_work(struct work_struct *work)
+{
+	struct firedtv *fdtv =
+			container_of(work, struct firedtv, remote_ctrl_work);
+
+	/* Should it be rescheduled in failure cases? */
+	avc_register_remote_control(fdtv);
+}
+
+#if 0 /* FIXME: unused */
+int avc_tuner_host2ca(struct firedtv *fdtv)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+	c->operand[6] = 0; /* more/last */
+	c->operand[7] = 0; /* length */
+
+	c->length = 12;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	return 0;
+}
+#endif
+
+static int get_ca_object_pos(struct avc_response_frame *r)
+{
+	int length = 1;
+
+	/* Check length of length field */
+	if (r->operand[7] & 0x80)
+		length = (r->operand[7] & 0x7f) + 1;
+	return length + 7;
+}
+
+static int get_ca_object_length(struct avc_response_frame *r)
+{
+#if 0 /* FIXME: unused */
+	int size = 0;
+	int i;
+
+	if (r->operand[7] & 0x80)
+		for (i = 0; i < (r->operand[7] & 0x7f); i++) {
+			size <<= 8;
+			size += r->operand[8 + i];
+		}
+#endif
+	return r->operand[7];
+}
+
+int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer;
+	int pos;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+
+	c->length = 12;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	/* FIXME: check response code and validate response data */
+
+	pos = get_ca_object_pos(r);
+	app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff;
+	app_info[1] = (EN50221_TAG_APP_INFO >>  8) & 0xff;
+	app_info[2] = (EN50221_TAG_APP_INFO >>  0) & 0xff;
+	app_info[3] = 6 + r->operand[pos + 4];
+	app_info[4] = 0x01;
+	memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
+	*len = app_info[3] + 4;
+
+	return 0;
+}
+
+int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer;
+	int pos;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+
+	c->length = 12;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	pos = get_ca_object_pos(r);
+	app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
+	app_info[1] = (EN50221_TAG_CA_INFO >>  8) & 0xff;
+	app_info[2] = (EN50221_TAG_CA_INFO >>  0) & 0xff;
+	app_info[3] = 2;
+	app_info[4] = r->operand[pos + 0];
+	app_info[5] = r->operand[pos + 1];
+	*len = app_info[3] + 4;
+
+	return 0;
+}
+
+int avc_ca_reset(struct firedtv *fdtv)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */
+	c->operand[6] = 0; /* more/last */
+	c->operand[7] = 1; /* length */
+	c->operand[8] = 0; /* force hardware reset */
+
+	c->length = 12;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	return 0;
+}
+
+int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer;
+	int list_management;
+	int program_info_length;
+	int pmt_cmd_id;
+	int read_pos;
+	int write_pos;
+	int es_info_length;
+	int crc32_csum;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) {
+		dev_info(fdtv->device, "forcing list_management to ONLY\n");
+		msg[0] = EN50221_LIST_MANAGEMENT_ONLY;
+	}
+	/* We take the cmd_id from the programme level only! */
+	list_management = msg[0];
+	program_info_length = ((msg[4] & 0x0f) << 8) + msg[5];
+	if (program_info_length > 0)
+		program_info_length--; /* Remove pmt_cmd_id */
+	pmt_cmd_id = msg[6];
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */
+	c->operand[6] = 0; /* more/last */
+	/* c->operand[7] = XXXprogram_info_length + 17; */ /* length */
+	c->operand[8] = list_management;
+	c->operand[9] = 0x01; /* pmt_cmd=OK_descramble */
+
+	/* TS program map table */
+
+	c->operand[10] = 0x02; /* Table id=2 */
+	c->operand[11] = 0x80; /* Section syntax + length */
+	/* c->operand[12] = XXXprogram_info_length + 12; */
+	c->operand[13] = msg[1]; /* Program number */
+	c->operand[14] = msg[2];
+	c->operand[15] = 0x01; /* Version number=0 + current/next=1 */
+	c->operand[16] = 0x00; /* Section number=0 */
+	c->operand[17] = 0x00; /* Last section number=0 */
+	c->operand[18] = 0x1f; /* PCR_PID=1FFF */
+	c->operand[19] = 0xff;
+	c->operand[20] = (program_info_length >> 8); /* Program info length */
+	c->operand[21] = (program_info_length & 0xff);
+
+	/* CA descriptors at programme level */
+	read_pos = 6;
+	write_pos = 22;
+	if (program_info_length > 0) {
+		pmt_cmd_id = msg[read_pos++];
+		if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
+			dev_err(fdtv->device,
+				"invalid pmt_cmd_id %d\n", pmt_cmd_id);
+
+		memcpy(&c->operand[write_pos], &msg[read_pos],
+		       program_info_length);
+		read_pos += program_info_length;
+		write_pos += program_info_length;
+	}
+	while (read_pos < length) {
+		c->operand[write_pos++] = msg[read_pos++];
+		c->operand[write_pos++] = msg[read_pos++];
+		c->operand[write_pos++] = msg[read_pos++];
+		es_info_length =
+			((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1];
+		read_pos += 2;
+		if (es_info_length > 0)
+			es_info_length--; /* Remove pmt_cmd_id */
+		c->operand[write_pos++] = es_info_length >> 8;
+		c->operand[write_pos++] = es_info_length & 0xff;
+		if (es_info_length > 0) {
+			pmt_cmd_id = msg[read_pos++];
+			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
+				dev_err(fdtv->device, "invalid pmt_cmd_id %d "
+					"at stream level\n", pmt_cmd_id);
+
+			memcpy(&c->operand[write_pos], &msg[read_pos],
+			       es_info_length);
+			read_pos += es_info_length;
+			write_pos += es_info_length;
+		}
+	}
+
+	/* CRC */
+	c->operand[write_pos++] = 0x00;
+	c->operand[write_pos++] = 0x00;
+	c->operand[write_pos++] = 0x00;
+	c->operand[write_pos++] = 0x00;
+
+	c->operand[7] = write_pos - 8;
+	c->operand[12] = write_pos - 13;
+
+	crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1);
+	c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff;
+	c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
+	c->operand[write_pos - 2] = (crc32_csum >>  8) & 0xff;
+	c->operand[write_pos - 1] = (crc32_csum >>  0) & 0xff;
+
+	c->length = ALIGN(3 + write_pos, 4);
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	if (r->response != AVC_RESPONSE_ACCEPTED) {
+		dev_err(fdtv->device,
+			"CA PMT failed with response 0x%x\n", r->response);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
+	c->operand[6] = 0; /* more/last */
+	c->operand[7] = 0; /* length */
+
+	c->length = 12;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	/* FIXME: check response code and validate response data */
+
+	*interval = r->operand[get_ca_object_pos(r)];
+
+	return 0;
+}
+
+int avc_ca_enter_menu(struct firedtv *fdtv)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer; /* FIXME: unused */
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
+	c->operand[6] = 0; /* more/last */
+	c->operand[7] = 0; /* length */
+
+	c->length = 12;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	return 0;
+}
+
+int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
+{
+	char buffer[sizeof(struct avc_command_frame)];
+	struct avc_command_frame *c = (void *)buffer;
+	struct avc_response_frame *r = (void *)buffer;
+
+	memset(c, 0, sizeof(*c));
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
+	c->operand[6] = 0; /* more/last */
+	c->operand[7] = 0; /* length */
+
+	c->length = 12;
+
+	if (avc_write(fdtv, c, r) < 0)
+		return -EIO;
+
+	/* FIXME: check response code and validate response data */
+
+	*len = get_ca_object_length(r);
+	memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
+
+	return 0;
+}
+
+#define CMP_OUTPUT_PLUG_CONTROL_REG_0	0xfffff0000904ULL
+
+static int cmp_read(struct firedtv *fdtv, void *buf, u64 addr, size_t len)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
+
+	ret = fdtv->backend->read(fdtv, addr, buf, len);
+	if (ret < 0)
+		dev_err(fdtv->device, "CMP: read I/O error\n");
+
+	mutex_unlock(&fdtv->avc_mutex);
+	return ret;
+}
+
+static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&fdtv->avc_mutex))
+		return -EINTR;
+
+	ret = fdtv->backend->lock(fdtv, addr, data, arg);
+	if (ret < 0)
+		dev_err(fdtv->device, "CMP: lock I/O error\n");
+
+	mutex_unlock(&fdtv->avc_mutex);
+	return ret;
+}
+
+static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
+{
+	return (be32_to_cpu(opcr) >> shift) & mask;
+}
+
+static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
+{
+	*opcr &= ~cpu_to_be32(mask << shift);
+	*opcr |= cpu_to_be32((value & mask) << shift);
+}
+
+#define get_opcr_online(v)		get_opcr((v), 0x1, 31)
+#define get_opcr_p2p_connections(v)	get_opcr((v), 0x3f, 24)
+#define get_opcr_channel(v)		get_opcr((v), 0x3f, 16)
+
+#define set_opcr_p2p_connections(p, v)	set_opcr((p), (v), 0x3f, 24)
+#define set_opcr_channel(p, v)		set_opcr((p), (v), 0x3f, 16)
+#define set_opcr_data_rate(p, v)	set_opcr((p), (v), 0x3, 14)
+#define set_opcr_overhead_id(p, v)	set_opcr((p), (v), 0xf, 10)
+
+int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
+{
+	__be32 old_opcr, opcr;
+	u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
+	int attempts = 0;
+	int ret;
+
+	ret = cmp_read(fdtv, &opcr, opcr_address, 4);
+	if (ret < 0)
+		return ret;
+
+repeat:
+	if (!get_opcr_online(opcr)) {
+		dev_err(fdtv->device, "CMP: output offline\n");
+		return -EBUSY;
+	}
+
+	old_opcr = opcr;
+
+	if (get_opcr_p2p_connections(opcr)) {
+		if (get_opcr_channel(opcr) != channel) {
+			dev_err(fdtv->device, "CMP: cannot change channel\n");
+			return -EBUSY;
+		}
+		dev_info(fdtv->device, "CMP: overlaying connection\n");
+
+		/* We don't allocate isochronous resources. */
+	} else {
+		set_opcr_channel(&opcr, channel);
+		set_opcr_data_rate(&opcr, 2); /* S400 */
+
+		/* FIXME: this is for the worst case - optimize */
+		set_opcr_overhead_id(&opcr, 0);
+
+		/*
+		 * FIXME: allocate isochronous channel and bandwidth at IRM
+		 * fdtv->backend->alloc_resources(fdtv, channels_mask, bw);
+		 */
+	}
+
+	set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1);
+
+	ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr);
+	if (ret < 0)
+		return ret;
+
+	if (old_opcr != opcr) {
+		/*
+		 * FIXME: if old_opcr.P2P_Connections > 0,
+		 * deallocate isochronous channel and bandwidth at IRM
+		 * if (...)
+		 *	fdtv->backend->dealloc_resources(fdtv, channel, bw);
+		 */
+
+		if (++attempts < 6) /* arbitrary limit */
+			goto repeat;
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
+{
+	__be32 old_opcr, opcr;
+	u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
+	int attempts = 0;
+
+	if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0)
+		return;
+
+repeat:
+	if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) ||
+	    get_opcr_channel(opcr) != channel) {
+		dev_err(fdtv->device, "CMP: no connection to break\n");
+		return;
+	}
+
+	old_opcr = opcr;
+	set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1);
+
+	if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr) < 0)
+		return;
+
+	if (old_opcr != opcr) {
+		/*
+		 * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
+		 * owner, deallocate isochronous channel and bandwidth at IRM
+		 * if (...)
+		 *	fdtv->backend->dealloc_resources(fdtv, channel, bw);
+		 */
+
+		if (++attempts < 6) /* arbitrary limit */
+			goto repeat;
+	}
+}
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c
new file mode 100644
index 0000000..eeb80d0
--- /dev/null
+++ b/drivers/media/dvb/firewire/firedtv-ci.c
@@ -0,0 +1,260 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	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/device.h>
+#include <linux/dvb/ca.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+
+#include <dvbdev.h>
+
+#include "firedtv.h"
+
+#define EN50221_TAG_APP_INFO_ENQUIRY	0x9f8020
+#define EN50221_TAG_CA_INFO_ENQUIRY	0x9f8030
+#define EN50221_TAG_CA_PMT		0x9f8032
+#define EN50221_TAG_ENTER_MENU		0x9f8022
+
+static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
+{
+	return stat->ca_initialization_status	== 1 &&
+	       stat->ca_error_flag		== 0 &&
+	       stat->ca_dvb_flag		== 1 &&
+	       stat->ca_module_present_status	== 1;
+}
+
+static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
+{
+	int flags = 0;
+
+	if (stat->ca_module_present_status == 1)
+		flags |= CA_CI_MODULE_PRESENT;
+	if (stat->ca_initialization_status == 1 &&
+	    stat->ca_error_flag            == 0 &&
+	    stat->ca_dvb_flag              == 1)
+		flags |= CA_CI_MODULE_READY;
+	return flags;
+}
+
+static int fdtv_ca_reset(struct firedtv *fdtv)
+{
+	return avc_ca_reset(fdtv) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_get_caps(void *arg)
+{
+	struct ca_caps *cap = arg;
+
+	cap->slot_num = 1;
+	cap->slot_type = CA_CI;
+	cap->descr_num = 1;
+	cap->descr_type = CA_ECD;
+	return 0;
+}
+
+static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
+{
+	struct firedtv_tuner_status stat;
+	struct ca_slot_info *slot = arg;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EFAULT;
+
+	if (slot->num != 0)
+		return -EFAULT;
+
+	slot->type = CA_CI;
+	slot->flags = fdtv_get_ca_flags(&stat);
+	return 0;
+}
+
+static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *reply = arg;
+
+	return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *reply = arg;
+
+	return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *reply = arg;
+
+	return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
+{
+	struct firedtv_tuner_status stat;
+	int err;
+
+	switch (fdtv->ca_last_command) {
+	case EN50221_TAG_APP_INFO_ENQUIRY:
+		err = fdtv_ca_app_info(fdtv, arg);
+		break;
+	case EN50221_TAG_CA_INFO_ENQUIRY:
+		err = fdtv_ca_info(fdtv, arg);
+		break;
+	default:
+		if (avc_tuner_status(fdtv, &stat))
+			err = -EFAULT;
+		else if (stat.ca_mmi == 1)
+			err = fdtv_ca_get_mmi(fdtv, arg);
+		else {
+			dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
+				 fdtv->ca_last_command);
+			err = -EFAULT;
+		}
+	}
+	fdtv->ca_last_command = 0;
+	return err;
+}
+
+static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *msg = arg;
+	int data_pos;
+	int data_length;
+	int i;
+
+	data_pos = 4;
+	if (msg->msg[3] & 0x80) {
+		data_length = 0;
+		for (i = 0; i < (msg->msg[3] & 0x7f); i++)
+			data_length = (data_length << 8) + msg->msg[data_pos++];
+	} else {
+		data_length = msg->msg[3];
+	}
+
+	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0;
+}
+
+static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *msg = arg;
+	int err;
+
+	/* Do we need a semaphore for this? */
+	fdtv->ca_last_command =
+		(msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
+	switch (fdtv->ca_last_command) {
+	case EN50221_TAG_CA_PMT:
+		err = fdtv_ca_pmt(fdtv, arg);
+		break;
+	case EN50221_TAG_APP_INFO_ENQUIRY:
+		/* handled in ca_get_msg */
+		err = 0;
+		break;
+	case EN50221_TAG_CA_INFO_ENQUIRY:
+		/* handled in ca_get_msg */
+		err = 0;
+		break;
+	case EN50221_TAG_ENTER_MENU:
+		err = avc_ca_enter_menu(fdtv);
+		break;
+	default:
+		dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
+			fdtv->ca_last_command);
+		err = -EFAULT;
+	}
+	return err;
+}
+
+static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, void *arg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct firedtv *fdtv = dvbdev->priv;
+	struct firedtv_tuner_status stat;
+	int err;
+
+	switch (cmd) {
+	case CA_RESET:
+		err = fdtv_ca_reset(fdtv);
+		break;
+	case CA_GET_CAP:
+		err = fdtv_ca_get_caps(arg);
+		break;
+	case CA_GET_SLOT_INFO:
+		err = fdtv_ca_get_slot_info(fdtv, arg);
+		break;
+	case CA_GET_MSG:
+		err = fdtv_ca_get_msg(fdtv, arg);
+		break;
+	case CA_SEND_MSG:
+		err = fdtv_ca_send_msg(fdtv, arg);
+		break;
+	default:
+		dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
+		err = -EOPNOTSUPP;
+	}
+
+	/* FIXME Is this necessary? */
+	avc_tuner_status(fdtv, &stat);
+
+	return err;
+}
+
+static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
+{
+	return POLLIN;
+}
+
+static struct file_operations fdtv_ca_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= dvb_generic_ioctl,
+	.open		= dvb_generic_open,
+	.release	= dvb_generic_release,
+	.poll		= fdtv_ca_io_poll,
+};
+
+static struct dvb_device fdtv_ca = {
+	.users		= 1,
+	.readers	= 1,
+	.writers	= 1,
+	.fops		= &fdtv_ca_fops,
+	.kernel_ioctl	= fdtv_ca_ioctl,
+};
+
+int fdtv_ca_register(struct firedtv *fdtv)
+{
+	struct firedtv_tuner_status stat;
+	int err;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	if (!fdtv_ca_ready(&stat))
+		return -EFAULT;
+
+	err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
+				  &fdtv_ca, fdtv, DVB_DEVICE_CA);
+
+	if (stat.ca_application_info == 0)
+		dev_err(fdtv->device, "CaApplicationInfo is not set\n");
+	if (stat.ca_date_time_request == 1)
+		avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
+
+	return err;
+}
+
+void fdtv_ca_release(struct firedtv *fdtv)
+{
+	if (fdtv->cadev)
+		dvb_unregister_device(fdtv->cadev);
+}
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c
new file mode 100644
index 0000000..9d308dd
--- /dev/null
+++ b/drivers/media/dvb/firewire/firedtv-dvb.c
@@ -0,0 +1,364 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	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/bitops.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <dmxdev.h>
+#include <dvb_demux.h>
+#include <dvbdev.h>
+#include <dvb_frontend.h>
+
+#include "firedtv.h"
+
+static int alloc_channel(struct firedtv *fdtv)
+{
+	int i;
+
+	for (i = 0; i < 16; i++)
+		if (!__test_and_set_bit(i, &fdtv->channel_active))
+			break;
+	return i;
+}
+
+static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
+{
+	int i, n;
+
+	for (i = 0, n = 0; i < 16; i++)
+		if (test_bit(i, &fdtv->channel_active))
+			pid[n++] = fdtv->channel_pid[i];
+	*pidc = n;
+}
+
+static inline void dealloc_channel(struct firedtv *fdtv, int i)
+{
+	__clear_bit(i, &fdtv->channel_active);
+}
+
+int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct firedtv *fdtv = dvbdmxfeed->demux->priv;
+	int pidc, c, ret;
+	u16 pids[16];
+
+	switch (dvbdmxfeed->type) {
+	case DMX_TYPE_TS:
+	case DMX_TYPE_SEC:
+		break;
+	default:
+		dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
+			dvbdmxfeed->type);
+		return -EINVAL;
+	}
+
+	if (mutex_lock_interruptible(&fdtv->demux_mutex))
+		return -EINTR;
+
+	if (dvbdmxfeed->type == DMX_TYPE_TS) {
+		switch (dvbdmxfeed->pes_type) {
+		case DMX_TS_PES_VIDEO:
+		case DMX_TS_PES_AUDIO:
+		case DMX_TS_PES_TELETEXT:
+		case DMX_TS_PES_PCR:
+		case DMX_TS_PES_OTHER:
+			c = alloc_channel(fdtv);
+			break;
+		default:
+			dev_err(fdtv->device,
+				"can't start dmx feed: invalid pes type %u\n",
+				dvbdmxfeed->pes_type);
+			ret = -EINVAL;
+			goto out;
+		}
+	} else {
+		c = alloc_channel(fdtv);
+	}
+
+	if (c > 15) {
+		dev_err(fdtv->device, "can't start dmx feed: busy\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
+	fdtv->channel_pid[c] = dvbdmxfeed->pid;
+	collect_channels(fdtv, &pidc, pids);
+
+	if (dvbdmxfeed->pid == 8192) {
+		ret = avc_tuner_get_ts(fdtv);
+		if (ret) {
+			dealloc_channel(fdtv, c);
+			dev_err(fdtv->device, "can't get TS\n");
+			goto out;
+		}
+	} else {
+		ret = avc_tuner_set_pids(fdtv, pidc, pids);
+		if (ret) {
+			dealloc_channel(fdtv, c);
+			dev_err(fdtv->device, "can't set PIDs\n");
+			goto out;
+		}
+	}
+out:
+	mutex_unlock(&fdtv->demux_mutex);
+
+	return ret;
+}
+
+int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *demux = dvbdmxfeed->demux;
+	struct firedtv *fdtv = demux->priv;
+	int pidc, c, ret;
+	u16 pids[16];
+
+	if (dvbdmxfeed->type == DMX_TYPE_TS &&
+	    !((dvbdmxfeed->ts_type & TS_PACKET) &&
+	      (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
+
+		if (dvbdmxfeed->ts_type & TS_DECODER) {
+			if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
+			    !demux->pesfilter[dvbdmxfeed->pes_type])
+				return -EINVAL;
+
+			demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
+			demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
+		}
+
+		if (!(dvbdmxfeed->ts_type & TS_DECODER &&
+		      dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
+			return 0;
+	}
+
+	if (mutex_lock_interruptible(&fdtv->demux_mutex))
+		return -EINTR;
+
+	c = (unsigned long)dvbdmxfeed->priv;
+	dealloc_channel(fdtv, c);
+	collect_channels(fdtv, &pidc, pids);
+
+	ret = avc_tuner_set_pids(fdtv, pidc, pids);
+
+	mutex_unlock(&fdtv->demux_mutex);
+
+	return ret;
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+int fdtv_dvb_register(struct firedtv *fdtv)
+{
+	int err;
+
+	err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
+				   THIS_MODULE, fdtv->device, adapter_nr);
+	if (err < 0)
+		goto fail_log;
+
+	/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
+	fdtv->demux.dmx.capabilities = 0;
+
+	fdtv->demux.priv	= fdtv;
+	fdtv->demux.filternum	= 16;
+	fdtv->demux.feednum	= 16;
+	fdtv->demux.start_feed	= fdtv_start_feed;
+	fdtv->demux.stop_feed	= fdtv_stop_feed;
+	fdtv->demux.write_to_decoder = NULL;
+
+	err = dvb_dmx_init(&fdtv->demux);
+	if (err)
+		goto fail_unreg_adapter;
+
+	fdtv->dmxdev.filternum    = 16;
+	fdtv->dmxdev.demux        = &fdtv->demux.dmx;
+	fdtv->dmxdev.capabilities = 0;
+
+	err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
+	if (err)
+		goto fail_dmx_release;
+
+	fdtv->frontend.source = DMX_FRONTEND_0;
+
+	err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+	if (err)
+		goto fail_dmxdev_release;
+
+	err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
+					       &fdtv->frontend);
+	if (err)
+		goto fail_rem_frontend;
+
+	dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
+
+	fdtv_frontend_init(fdtv);
+	err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
+	if (err)
+		goto fail_net_release;
+
+	err = fdtv_ca_register(fdtv);
+	if (err)
+		dev_info(fdtv->device,
+			 "Conditional Access Module not enabled\n");
+	return 0;
+
+fail_net_release:
+	dvb_net_release(&fdtv->dvbnet);
+	fdtv->demux.dmx.close(&fdtv->demux.dmx);
+fail_rem_frontend:
+	fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+fail_dmxdev_release:
+	dvb_dmxdev_release(&fdtv->dmxdev);
+fail_dmx_release:
+	dvb_dmx_release(&fdtv->demux);
+fail_unreg_adapter:
+	dvb_unregister_adapter(&fdtv->adapter);
+fail_log:
+	dev_err(fdtv->device, "DVB initialization failed\n");
+	return err;
+}
+
+void fdtv_dvb_unregister(struct firedtv *fdtv)
+{
+	fdtv_ca_release(fdtv);
+	dvb_unregister_frontend(&fdtv->fe);
+	dvb_net_release(&fdtv->dvbnet);
+	fdtv->demux.dmx.close(&fdtv->demux.dmx);
+	fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+	dvb_dmxdev_release(&fdtv->dmxdev);
+	dvb_dmx_release(&fdtv->demux);
+	dvb_unregister_adapter(&fdtv->adapter);
+}
+
+const char *fdtv_model_names[] = {
+	[FIREDTV_UNKNOWN] = "unknown type",
+	[FIREDTV_DVB_S]   = "FireDTV S/CI",
+	[FIREDTV_DVB_C]   = "FireDTV C/CI",
+	[FIREDTV_DVB_T]   = "FireDTV T/CI",
+	[FIREDTV_DVB_S2]  = "FireDTV S2  ",
+};
+
+struct firedtv *fdtv_alloc(struct device *dev,
+			   const struct firedtv_backend *backend,
+			   const char *name, size_t name_len)
+{
+	struct firedtv *fdtv;
+	int i;
+
+	fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
+	if (!fdtv)
+		return NULL;
+
+	dev->driver_data	= fdtv;
+	fdtv->device		= dev;
+	fdtv->isochannel	= -1;
+	fdtv->voltage		= 0xff;
+	fdtv->tone		= 0xff;
+	fdtv->backend		= backend;
+
+	mutex_init(&fdtv->avc_mutex);
+	init_waitqueue_head(&fdtv->avc_wait);
+	fdtv->avc_reply_received = true;
+	mutex_init(&fdtv->demux_mutex);
+	INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
+
+	for (i = ARRAY_SIZE(fdtv_model_names); --i; )
+		if (strlen(fdtv_model_names[i]) <= name_len &&
+		    strncmp(name, fdtv_model_names[i], name_len) == 0)
+			break;
+	fdtv->type = i;
+
+	return fdtv;
+}
+
+#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
+		     IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
+
+#define DIGITAL_EVERYWHERE_OUI	0x001287
+#define AVC_UNIT_SPEC_ID_ENTRY	0x00a02d
+#define AVC_SW_VERSION_ENTRY	0x010001
+
+static struct ieee1394_device_id fdtv_id_table[] = {
+	{
+		/* FloppyDTV S/CI and FloppyDTV S2 */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000024,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FloppyDTV T/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000025,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FloppyDTV C/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000026,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FireDTV S/CI and FloppyDTV S2 */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000034,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FireDTV T/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000035,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FireDTV C/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000036,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {}
+};
+MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
+
+static int __init fdtv_init(void)
+{
+	return fdtv_1394_init(fdtv_id_table);
+}
+
+static void __exit fdtv_exit(void)
+{
+	fdtv_1394_exit();
+}
+
+module_init(fdtv_init);
+module_exit(fdtv_exit);
+
+MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
+MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
+MODULE_DESCRIPTION("FireDTV DVB Driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff --git a/drivers/media/dvb/firewire/firedtv-fe.c b/drivers/media/dvb/firewire/firedtv-fe.c
new file mode 100644
index 0000000..7ba4363
--- /dev/null
+++ b/drivers/media/dvb/firewire/firedtv-fe.c
@@ -0,0 +1,247 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	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/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <dvb_frontend.h>
+
+#include "firedtv.h"
+
+static int fdtv_dvb_init(struct dvb_frontend *fe)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	int err;
+
+	/* FIXME - allocate free channel at IRM */
+	fdtv->isochannel = fdtv->adapter.num;
+
+	err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
+					  fdtv->isochannel);
+	if (err) {
+		dev_err(fdtv->device,
+			"could not establish point to point connection\n");
+		return err;
+	}
+
+	return fdtv->backend->start_iso(fdtv);
+}
+
+static int fdtv_sleep(struct dvb_frontend *fe)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+
+	fdtv->backend->stop_iso(fdtv);
+	cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
+	fdtv->isochannel = -1;
+	return 0;
+}
+
+#define LNBCONTROL_DONTCARE 0xff
+
+static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
+				       struct dvb_diseqc_master_cmd *cmd)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+
+	return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
+			       LNBCONTROL_DONTCARE, 1, cmd);
+}
+
+static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
+				  fe_sec_mini_cmd_t minicmd)
+{
+	return 0;
+}
+
+static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+
+	fdtv->tone = tone;
+	return 0;
+}
+
+static int fdtv_set_voltage(struct dvb_frontend *fe,
+			    fe_sec_voltage_t voltage)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+
+	fdtv->voltage = voltage;
+	return 0;
+}
+
+static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	struct firedtv_tuner_status stat;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	if (stat.no_rf)
+		*status = 0;
+	else
+		*status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
+			  FE_HAS_CARRIER | FE_HAS_LOCK;
+	return 0;
+}
+
+static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	struct firedtv_tuner_status stat;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	*ber = stat.ber;
+	return 0;
+}
+
+static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	struct firedtv_tuner_status stat;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	*strength = stat.signal_strength << 8;
+	return 0;
+}
+
+static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	struct firedtv_tuner_status stat;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	/* C/N[dB] = -10 * log10(snr / 65535) */
+	*snr = stat.carrier_noise_ratio * 257;
+	return 0;
+}
+
+static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	return -EOPNOTSUPP;
+}
+
+#define ACCEPTED 0x9
+
+static int fdtv_set_frontend(struct dvb_frontend *fe,
+			     struct dvb_frontend_parameters *params)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+
+	/* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */
+	if (avc_tuner_dsd(fdtv, params) != ACCEPTED)
+		return -EINVAL;
+	else
+		return 0; /* not sure of this... */
+}
+
+static int fdtv_get_frontend(struct dvb_frontend *fe,
+			     struct dvb_frontend_parameters *params)
+{
+	return -EOPNOTSUPP;
+}
+
+void fdtv_frontend_init(struct firedtv *fdtv)
+{
+	struct dvb_frontend_ops *ops = &fdtv->fe.ops;
+	struct dvb_frontend_info *fi = &ops->info;
+
+	ops->init			= fdtv_dvb_init;
+	ops->sleep			= fdtv_sleep;
+
+	ops->set_frontend		= fdtv_set_frontend;
+	ops->get_frontend		= fdtv_get_frontend;
+
+	ops->read_status		= fdtv_read_status;
+	ops->read_ber			= fdtv_read_ber;
+	ops->read_signal_strength	= fdtv_read_signal_strength;
+	ops->read_snr			= fdtv_read_snr;
+	ops->read_ucblocks		= fdtv_read_uncorrected_blocks;
+
+	ops->diseqc_send_master_cmd 	= fdtv_diseqc_send_master_cmd;
+	ops->diseqc_send_burst		= fdtv_diseqc_send_burst;
+	ops->set_tone			= fdtv_set_tone;
+	ops->set_voltage		= fdtv_set_voltage;
+
+	switch (fdtv->type) {
+	case FIREDTV_DVB_S:
+	case FIREDTV_DVB_S2:
+		fi->type		= FE_QPSK;
+
+		fi->frequency_min	= 950000;
+		fi->frequency_max	= 2150000;
+		fi->frequency_stepsize	= 125;
+		fi->symbol_rate_min	= 1000000;
+		fi->symbol_rate_max	= 40000000;
+
+		fi->caps 		= FE_CAN_INVERSION_AUTO	|
+					  FE_CAN_FEC_1_2	|
+					  FE_CAN_FEC_2_3	|
+					  FE_CAN_FEC_3_4	|
+					  FE_CAN_FEC_5_6	|
+					  FE_CAN_FEC_7_8	|
+					  FE_CAN_FEC_AUTO	|
+					  FE_CAN_QPSK;
+		break;
+
+	case FIREDTV_DVB_C:
+		fi->type		= FE_QAM;
+
+		fi->frequency_min	= 47000000;
+		fi->frequency_max	= 866000000;
+		fi->frequency_stepsize	= 62500;
+		fi->symbol_rate_min	= 870000;
+		fi->symbol_rate_max	= 6900000;
+
+		fi->caps 		= FE_CAN_INVERSION_AUTO |
+					  FE_CAN_QAM_16		|
+					  FE_CAN_QAM_32		|
+					  FE_CAN_QAM_64		|
+					  FE_CAN_QAM_128	|
+					  FE_CAN_QAM_256	|
+					  FE_CAN_QAM_AUTO;
+		break;
+
+	case FIREDTV_DVB_T:
+		fi->type		= FE_OFDM;
+
+		fi->frequency_min	= 49000000;
+		fi->frequency_max	= 861000000;
+		fi->frequency_stepsize	= 62500;
+
+		fi->caps 		= FE_CAN_INVERSION_AUTO		|
+					  FE_CAN_FEC_2_3		|
+					  FE_CAN_TRANSMISSION_MODE_AUTO |
+					  FE_CAN_GUARD_INTERVAL_AUTO	|
+					  FE_CAN_HIERARCHY_AUTO;
+		break;
+
+	default:
+		dev_err(fdtv->device, "no frontend for model type %d\n",
+			fdtv->type);
+	}
+	strcpy(fi->name, fdtv_model_names[fdtv->type]);
+
+	fdtv->fe.dvb = &fdtv->adapter;
+	fdtv->fe.sec_priv = fdtv;
+}
diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c
new file mode 100644
index 0000000..46a6324
--- /dev/null
+++ b/drivers/media/dvb/firewire/firedtv-rc.c
@@ -0,0 +1,190 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.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.
+ */
+
+#include <linux/bitops.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "firedtv.h"
+
+/* fixed table with older keycodes, geared towards MythTV */
+const static u16 oldtable[] = {
+
+	/* code from device: 0x4501...0x451f */
+
+	KEY_ESC,
+	KEY_F9,
+	KEY_1,
+	KEY_2,
+	KEY_3,
+	KEY_4,
+	KEY_5,
+	KEY_6,
+	KEY_7,
+	KEY_8,
+	KEY_9,
+	KEY_I,
+	KEY_0,
+	KEY_ENTER,
+	KEY_RED,
+	KEY_UP,
+	KEY_GREEN,
+	KEY_F10,
+	KEY_SPACE,
+	KEY_F11,
+	KEY_YELLOW,
+	KEY_DOWN,
+	KEY_BLUE,
+	KEY_Z,
+	KEY_P,
+	KEY_PAGEDOWN,
+	KEY_LEFT,
+	KEY_W,
+	KEY_RIGHT,
+	KEY_P,
+	KEY_M,
+
+	/* code from device: 0x4540...0x4542 */
+
+	KEY_R,
+	KEY_V,
+	KEY_C,
+};
+
+/* user-modifiable table for a remote as sold in 2008 */
+const static u16 keytable[] = {
+
+	/* code from device: 0x0300...0x031f */
+
+	[0x00] = KEY_POWER,
+	[0x01] = KEY_SLEEP,
+	[0x02] = KEY_STOP,
+	[0x03] = KEY_OK,
+	[0x04] = KEY_RIGHT,
+	[0x05] = KEY_1,
+	[0x06] = KEY_2,
+	[0x07] = KEY_3,
+	[0x08] = KEY_LEFT,
+	[0x09] = KEY_4,
+	[0x0a] = KEY_5,
+	[0x0b] = KEY_6,
+	[0x0c] = KEY_UP,
+	[0x0d] = KEY_7,
+	[0x0e] = KEY_8,
+	[0x0f] = KEY_9,
+	[0x10] = KEY_DOWN,
+	[0x11] = KEY_TITLE,	/* "OSD" - fixme */
+	[0x12] = KEY_0,
+	[0x13] = KEY_F20,	/* "16:9" - fixme */
+	[0x14] = KEY_SCREEN,	/* "FULL" - fixme */
+	[0x15] = KEY_MUTE,
+	[0x16] = KEY_SUBTITLE,
+	[0x17] = KEY_RECORD,
+	[0x18] = KEY_TEXT,
+	[0x19] = KEY_AUDIO,
+	[0x1a] = KEY_RED,
+	[0x1b] = KEY_PREVIOUS,
+	[0x1c] = KEY_REWIND,
+	[0x1d] = KEY_PLAYPAUSE,
+	[0x1e] = KEY_NEXT,
+	[0x1f] = KEY_VOLUMEUP,
+
+	/* code from device: 0x0340...0x0354 */
+
+	[0x20] = KEY_CHANNELUP,
+	[0x21] = KEY_F21,	/* "4:3" - fixme */
+	[0x22] = KEY_TV,
+	[0x23] = KEY_DVD,
+	[0x24] = KEY_VCR,
+	[0x25] = KEY_AUX,
+	[0x26] = KEY_GREEN,
+	[0x27] = KEY_YELLOW,
+	[0x28] = KEY_BLUE,
+	[0x29] = KEY_CHANNEL,	/* "CH.LIST" */
+	[0x2a] = KEY_VENDOR,	/* "CI" - fixme */
+	[0x2b] = KEY_VOLUMEDOWN,
+	[0x2c] = KEY_CHANNELDOWN,
+	[0x2d] = KEY_LAST,
+	[0x2e] = KEY_INFO,
+	[0x2f] = KEY_FORWARD,
+	[0x30] = KEY_LIST,
+	[0x31] = KEY_FAVORITES,
+	[0x32] = KEY_MENU,
+	[0x33] = KEY_EPG,
+	[0x34] = KEY_EXIT,
+};
+
+int fdtv_register_rc(struct firedtv *fdtv, struct device *dev)
+{
+	struct input_dev *idev;
+	int i, err;
+
+	idev = input_allocate_device();
+	if (!idev)
+		return -ENOMEM;
+
+	fdtv->remote_ctrl_dev = idev;
+	idev->name = "FireDTV remote control";
+	idev->dev.parent = dev;
+	idev->evbit[0] = BIT_MASK(EV_KEY);
+	idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL);
+	if (!idev->keycode) {
+		err = -ENOMEM;
+		goto fail;
+	}
+	idev->keycodesize = sizeof(keytable[0]);
+	idev->keycodemax = ARRAY_SIZE(keytable);
+
+	for (i = 0; i < ARRAY_SIZE(keytable); i++)
+		set_bit(keytable[i], idev->keybit);
+
+	err = input_register_device(idev);
+	if (err)
+		goto fail_free_keymap;
+
+	return 0;
+
+fail_free_keymap:
+	kfree(idev->keycode);
+fail:
+	input_free_device(idev);
+	return err;
+}
+
+void fdtv_unregister_rc(struct firedtv *fdtv)
+{
+	kfree(fdtv->remote_ctrl_dev->keycode);
+	input_unregister_device(fdtv->remote_ctrl_dev);
+}
+
+void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code)
+{
+	u16 *keycode = fdtv->remote_ctrl_dev->keycode;
+
+	if (code >= 0x0300 && code <= 0x031f)
+		code = keycode[code - 0x0300];
+	else if (code >= 0x0340 && code <= 0x0354)
+		code = keycode[code - 0x0320];
+	else if (code >= 0x4501 && code <= 0x451f)
+		code = oldtable[code - 0x4501];
+	else if (code >= 0x4540 && code <= 0x4542)
+		code = oldtable[code - 0x4521];
+	else {
+		printk(KERN_DEBUG "firedtv: invalid key code 0x%04x "
+		       "from remote control\n", code);
+		return;
+	}
+
+	input_report_key(fdtv->remote_ctrl_dev, code, 1);
+	input_report_key(fdtv->remote_ctrl_dev, code, 0);
+}
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h
new file mode 100644
index 0000000..d48530b
--- /dev/null
+++ b/drivers/media/dvb/firewire/firedtv.h
@@ -0,0 +1,182 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	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.
+ */
+
+#ifndef _FIREDTV_H
+#define _FIREDTV_H
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <demux.h>
+#include <dmxdev.h>
+#include <dvb_demux.h>
+#include <dvb_frontend.h>
+#include <dvb_net.h>
+#include <dvbdev.h>
+
+struct firedtv_tuner_status {
+	unsigned active_system:8;
+	unsigned searching:1;
+	unsigned moving:1;
+	unsigned no_rf:1;
+	unsigned input:1;
+	unsigned selected_antenna:7;
+	unsigned ber:32;
+	unsigned signal_strength:8;
+	unsigned raster_frequency:2;
+	unsigned rf_frequency:22;
+	unsigned man_dep_info_length:8;
+	unsigned front_end_error:1;
+	unsigned antenna_error:1;
+	unsigned front_end_power_status:1;
+	unsigned power_supply:1;
+	unsigned carrier_noise_ratio:16;
+	unsigned power_supply_voltage:8;
+	unsigned antenna_voltage:8;
+	unsigned firewire_bus_voltage:8;
+	unsigned ca_mmi:1;
+	unsigned ca_pmt_reply:1;
+	unsigned ca_date_time_request:1;
+	unsigned ca_application_info:1;
+	unsigned ca_module_present_status:1;
+	unsigned ca_dvb_flag:1;
+	unsigned ca_error_flag:1;
+	unsigned ca_initialization_status:1;
+};
+
+enum model_type {
+	FIREDTV_UNKNOWN = 0,
+	FIREDTV_DVB_S   = 1,
+	FIREDTV_DVB_C   = 2,
+	FIREDTV_DVB_T   = 3,
+	FIREDTV_DVB_S2  = 4,
+};
+
+struct device;
+struct input_dev;
+struct firedtv;
+
+struct firedtv_backend {
+	int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg);
+	int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
+	int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
+	int (*start_iso)(struct firedtv *fdtv);
+	void (*stop_iso)(struct firedtv *fdtv);
+};
+
+struct firedtv {
+	struct device *device;
+	struct list_head list;
+
+	struct dvb_adapter	adapter;
+	struct dmxdev		dmxdev;
+	struct dvb_demux	demux;
+	struct dmx_frontend	frontend;
+	struct dvb_net		dvbnet;
+	struct dvb_frontend	fe;
+
+	struct dvb_device	*cadev;
+	int			ca_last_command;
+	int			ca_time_interval;
+
+	struct mutex		avc_mutex;
+	wait_queue_head_t	avc_wait;
+	bool			avc_reply_received;
+	struct work_struct	remote_ctrl_work;
+	struct input_dev	*remote_ctrl_dev;
+
+	enum model_type		type;
+	char			subunit;
+	char			isochannel;
+	fe_sec_voltage_t	voltage;
+	fe_sec_tone_mode_t	tone;
+
+	const struct firedtv_backend *backend;
+	void			*backend_data;
+
+	struct mutex		demux_mutex;
+	unsigned long		channel_active;
+	u16			channel_pid[16];
+
+	size_t			response_length;
+	u8			response[512];
+};
+
+/* firedtv-1394.c */
+#ifdef CONFIG_DVB_FIREDTV_IEEE1394
+int fdtv_1394_init(struct ieee1394_device_id id_table[]);
+void fdtv_1394_exit(void);
+#else
+static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; }
+static inline void fdtv_1394_exit(void) {}
+#endif
+
+/* firedtv-avc.c */
+int avc_recv(struct firedtv *fdtv, void *data, size_t length);
+int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
+struct dvb_frontend_parameters;
+int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params);
+int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
+int avc_tuner_get_ts(struct firedtv *fdtv);
+int avc_identify_subunit(struct firedtv *fdtv);
+struct dvb_diseqc_master_cmd;
+int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
+		    char conttone, char nrdiseq,
+		    struct dvb_diseqc_master_cmd *diseqcmd);
+void avc_remote_ctrl_work(struct work_struct *work);
+int avc_register_remote_control(struct firedtv *fdtv);
+int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
+int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
+int avc_ca_reset(struct firedtv *fdtv);
+int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
+int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
+int avc_ca_enter_menu(struct firedtv *fdtv);
+int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
+int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
+void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
+
+/* firedtv-ci.c */
+int fdtv_ca_register(struct firedtv *fdtv);
+void fdtv_ca_release(struct firedtv *fdtv);
+
+/* firedtv-dvb.c */
+int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
+int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
+int fdtv_dvb_register(struct firedtv *fdtv);
+void fdtv_dvb_unregister(struct firedtv *fdtv);
+struct firedtv *fdtv_alloc(struct device *dev,
+			   const struct firedtv_backend *backend,
+			   const char *name, size_t name_len);
+extern const char *fdtv_model_names[];
+
+/* firedtv-fe.c */
+void fdtv_frontend_init(struct firedtv *fdtv);
+
+/* firedtv-rc.c */
+#ifdef CONFIG_DVB_FIREDTV_INPUT
+int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
+void fdtv_unregister_rc(struct firedtv *fdtv);
+void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
+#else
+static inline int fdtv_register_rc(struct firedtv *fdtv,
+				   struct device *dev) { return 0; }
+static inline void fdtv_unregister_rc(struct firedtv *fdtv) {}
+static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {}
+#endif
+
+#endif /* _FIREDTV_H */
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index 5d882a4..2ac738f 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -463,6 +463,8 @@
 	pcm->info_flags = 0;
 	pcm->private_data = dev;
 	strcpy(pcm->name, "Empia 28xx Capture");
+
+	snd_card_set_dev(card, &dev->udev->dev);
 	strcpy(card->driver, "Empia Em28xx Audio");
 	strcpy(card->shortname, "Em28xx Audio");
 	strcpy(card->longname, "Empia Em28xx Audio");
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index a1d6008..07c334f 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -1155,24 +1155,24 @@
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct pxa_camera_dev *pcdev = ici->priv;
-	const struct soc_camera_data_format *host_fmt, *cam_fmt = NULL;
-	const struct soc_camera_format_xlate *xlate;
+	const struct soc_camera_data_format *cam_fmt = NULL;
+	const struct soc_camera_format_xlate *xlate = NULL;
 	struct soc_camera_sense sense = {
 		.master_clock = pcdev->mclk,
 		.pixel_clock_max = pcdev->ciclk / 4,
 	};
-	int ret, buswidth;
+	int ret;
 
-	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
-	if (!xlate) {
-		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
-		return -EINVAL;
+	if (pixfmt) {
+		xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+		if (!xlate) {
+			dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+			return -EINVAL;
+		}
+
+		cam_fmt = xlate->cam_fmt;
 	}
 
-	buswidth = xlate->buswidth;
-	host_fmt = xlate->host_fmt;
-	cam_fmt = xlate->cam_fmt;
-
 	/* If PCLK is used to latch data from the sensor, check sense */
 	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
 		icd->sense = &sense;
@@ -1201,8 +1201,8 @@
 	}
 
 	if (pixfmt && !ret) {
-		icd->buswidth = buswidth;
-		icd->current_fmt = host_fmt;
+		icd->buswidth = xlate->buswidth;
+		icd->current_fmt = xlate->host_fmt;
 	}
 
 	return ret;
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 9a2586b..ddcb81d 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -603,21 +603,18 @@
 	const struct soc_camera_format_xlate *xlate;
 	int ret;
 
+	if (!pixfmt)
+		return icd->ops->set_fmt(icd, pixfmt, rect);
+
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
 		dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
-	switch (pixfmt) {
-	case 0:				/* Only geometry change */
-		ret = icd->ops->set_fmt(icd, pixfmt, rect);
-		break;
-	default:
-		ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect);
-	}
+	ret = icd->ops->set_fmt(icd, xlate->cam_fmt->fourcc, rect);
 
-	if (pixfmt && !ret) {
+	if (!ret) {
 		icd->buswidth = xlate->buswidth;
 		icd->current_fmt = xlate->host_fmt;
 		pcdev->camera_fmt = xlate->cam_fmt;
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index f26667a..cf99185 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -710,6 +710,7 @@
 
 static struct pci_device_id ilo_devices[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB204) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3307) },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, ilo_devices);
@@ -758,7 +759,7 @@
 	class_destroy(ilo_class);
 }
 
-MODULE_VERSION("0.06");
+MODULE_VERSION("1.0");
 MODULE_ALIAS(ILO_NAME);
 MODULE_DESCRIPTION(ILO_NAME);
 MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c
index 821d0ed..c76d6e5 100644
--- a/drivers/mtd/chips/map_rom.c
+++ b/drivers/mtd/chips/map_rom.c
@@ -19,6 +19,7 @@
 static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 static void maprom_nop (struct mtd_info *);
 static struct mtd_info *map_rom_probe(struct map_info *map);
+static int maprom_erase (struct mtd_info *mtd, struct erase_info *info);
 
 static struct mtd_chip_driver maprom_chipdrv = {
 	.probe	= map_rom_probe,
@@ -42,6 +43,7 @@
 	mtd->read = maprom_read;
 	mtd->write = maprom_write;
 	mtd->sync = maprom_nop;
+	mtd->erase = maprom_erase;
 	mtd->flags = MTD_CAP_ROM;
 	mtd->erasesize = map->size;
 	mtd->writesize = 1;
@@ -71,6 +73,12 @@
 	return -EIO;
 }
 
+static int maprom_erase (struct mtd_info *mtd, struct erase_info *info)
+{
+	/* We do our best 8) */
+	return -EROFS;
+}
+
 static int __init map_rom_init(void)
 {
 	register_mtd_chip_driver(&maprom_chipdrv);
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index a425d09..00248e8 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -267,22 +267,28 @@
 	if (*(szlength) != '+') {
 		devlength = simple_strtoul(szlength, &buffer, 0);
 		devlength = handle_unit(devlength, buffer) - devstart;
+		if (devlength < devstart)
+			goto err_out;
+
+		devlength -= devstart;
 	} else {
 		devlength = simple_strtoul(szlength + 1, &buffer, 0);
 		devlength = handle_unit(devlength, buffer);
 	}
 	T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",
 			devname, devstart, devlength);
-	if ((devstart < 0) || (devlength < 0) || (devlength % SLRAM_BLK_SZ != 0)) {
-		E("slram: Illegal start / length parameter.\n");
-		return(-EINVAL);
-	}
+	if (devlength % SLRAM_BLK_SZ != 0)
+		goto err_out;
 
 	if ((devstart = register_device(devname, devstart, devlength))){
 		unregister_devices();
 		return((int)devstart);
 	}
 	return(0);
+
+err_out:
+	E("slram: Illegal length parameter.\n");
+	return(-EINVAL);
 }
 
 #ifndef MODULE
diff --git a/drivers/mtd/lpddr/Kconfig b/drivers/mtd/lpddr/Kconfig
index acd4ea9..5a401d8 100644
--- a/drivers/mtd/lpddr/Kconfig
+++ b/drivers/mtd/lpddr/Kconfig
@@ -12,6 +12,7 @@
 	  DDR memories, intended for battery-operated systems.
 
 config MTD_QINFO_PROBE
+	depends on MTD_LPDDR
 	tristate "Detect flash chips by QINFO probe"
 	help
 	    Device Information for LPDDR chips is offered through the Overlay
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 0225cbb..043d50f 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -491,7 +491,7 @@
 
 config MTD_BFIN_ASYNC
 	tristate "Blackfin BF533-STAMP Flash Chip Support"
-	depends on BFIN533_STAMP && MTD_CFI
+	depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS
 	select MTD_PARTITIONS
 	default y
 	help
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index 6fec86a..576611f 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -152,14 +152,18 @@
 
 	if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) {
 		pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin);
+		kfree(state);
 		return -EBUSY;
 	}
 	gpio_direction_output(state->enet_flash_pin, 1);
 
 	pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
 	state->mtd = do_map_probe(memory->name, &state->map);
-	if (!state->mtd)
+	if (!state->mtd) {
+		gpio_free(state->enet_flash_pin);
+		kfree(state);
 		return -ENXIO;
+	}
 
 #ifdef CONFIG_MTD_PARTITIONS
 	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 5f7a245..424f17d 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -342,9 +342,9 @@
 	{ 0, }
 };
 
+#if 0
 MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
 
-#if 0
 static struct pci_driver ck804xrom_driver = {
 	.name =		MOD_NAME,
 	.id_table =	ck804xrom_pci_tbl,
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 8774366..4b122e7 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -29,6 +29,7 @@
 	struct map_info		map[MAX_RESOURCES];
 #ifdef CONFIG_MTD_PARTITIONS
 	int			nr_parts;
+	struct mtd_partition	*parts;
 #endif
 };
 
@@ -45,25 +46,26 @@
 
 	physmap_data = dev->dev.platform_data;
 
-#ifdef CONFIG_MTD_CONCAT
-	if (info->cmtd != info->mtd[0]) {
+#ifdef CONFIG_MTD_PARTITIONS
+	if (info->nr_parts) {
+		del_mtd_partitions(info->cmtd);
+		kfree(info->parts);
+	} else if (physmap_data->nr_parts)
+		del_mtd_partitions(info->cmtd);
+	else
 		del_mtd_device(info->cmtd);
+#else
+	del_mtd_device(info->cmtd);
+#endif
+
+#ifdef CONFIG_MTD_CONCAT
+	if (info->cmtd != info->mtd[0])
 		mtd_concat_destroy(info->cmtd);
-	}
 #endif
 
 	for (i = 0; i < MAX_RESOURCES; i++) {
-		if (info->mtd[i] != NULL) {
-#ifdef CONFIG_MTD_PARTITIONS
-			if (info->nr_parts || physmap_data->nr_parts)
-				del_mtd_partitions(info->mtd[i]);
-			else
-				del_mtd_device(info->mtd[i]);
-#else
-			del_mtd_device(info->mtd[i]);
-#endif
+		if (info->mtd[i] != NULL)
 			map_destroy(info->mtd[i]);
-		}
 	}
 	return 0;
 }
@@ -86,9 +88,6 @@
 	int err = 0;
 	int i;
 	int devices_found = 0;
-#ifdef CONFIG_MTD_PARTITIONS
-	struct mtd_partition *parts;
-#endif
 
 	physmap_data = dev->dev.platform_data;
 	if (physmap_data == NULL)
@@ -167,10 +166,11 @@
 		goto err_out;
 
 #ifdef CONFIG_MTD_PARTITIONS
-	err = parse_mtd_partitions(info->cmtd, part_probe_types, &parts, 0);
+	err = parse_mtd_partitions(info->cmtd, part_probe_types,
+				&info->parts, 0);
 	if (err > 0) {
-		add_mtd_partitions(info->cmtd, parts, err);
-		kfree(parts);
+		add_mtd_partitions(info->cmtd, info->parts, err);
+		info->nr_parts = err;
 		return 0;
 	}
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6bdfd47..a2f185f 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2342,6 +2342,17 @@
 	  To compile this driver as a module, choose M here.  The module
 	  will be called atl1e.
 
+config ATL1C
+	tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
+	depends on PCI && EXPERIMENTAL
+	select CRC32
+	select MII
+	help
+	  This driver supports the Atheros L1C gigabit ethernet adapter.
+
+	  To compile this driver as a module, choose M here.  The module
+	  will be called atl1c.
+
 config JME
 	tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
 	depends on PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a3c5c00..aca8492 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -17,6 +17,7 @@
 obj-$(CONFIG_ATL1) += atlx/
 obj-$(CONFIG_ATL2) += atlx/
 obj-$(CONFIG_ATL1E) += atl1e/
+obj-$(CONFIG_ATL1C) += atl1c/
 obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 obj-$(CONFIG_TEHUTI) += tehuti.o
 obj-$(CONFIG_ENIC) += enic/
diff --git a/drivers/net/atl1c/Makefile b/drivers/net/atl1c/Makefile
new file mode 100644
index 0000000..c37d966
--- /dev/null
+++ b/drivers/net/atl1c/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ATL1C) += atl1c.o
+atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
new file mode 100644
index 0000000..ac11b84
--- /dev/null
+++ b/drivers/net/atl1c/atl1c.h
@@ -0,0 +1,606 @@
+/*
+ * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; 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 _ATL1C_H_
+#define _ATL1C_H_
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/mii.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+#include <linux/tcp.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/workqueue.h>
+#include <net/checksum.h>
+#include <net/ip6_checksum.h>
+
+#include "atl1c_hw.h"
+
+/* Wake Up Filter Control */
+#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
+#define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
+#define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */
+#define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
+
+#define AT_VLAN_TO_TAG(_vlan, _tag)	   \
+	_tag =  ((((_vlan) >> 8) & 0xFF)  |\
+		 (((_vlan) & 0xFF) << 8))
+
+#define AT_TAG_TO_VLAN(_tag, _vlan) 	 \
+	_vlan = ((((_tag) >> 8) & 0xFF) |\
+		(((_tag) & 0xFF) << 8))
+
+#define SPEED_0		   0xffff
+#define HALF_DUPLEX        1
+#define FULL_DUPLEX        2
+
+#define AT_RX_BUF_SIZE		(ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)
+#define MAX_JUMBO_FRAME_SIZE 	(9*1024)
+#define MAX_TX_OFFLOAD_THRESH	(9*1024)
+
+#define AT_MAX_RECEIVE_QUEUE    4
+#define AT_DEF_RECEIVE_QUEUE	1
+#define AT_MAX_TRANSMIT_QUEUE	2
+
+#define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL
+#define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL
+
+#define AT_TX_WATCHDOG  (5 * HZ)
+#define AT_MAX_INT_WORK		5
+#define AT_TWSI_EEPROM_TIMEOUT 	100
+#define AT_HW_MAX_IDLE_DELAY 	10
+#define AT_SUSPEND_LINK_TIMEOUT 28
+
+#define AT_ASPM_L0S_TIMER	6
+#define AT_ASPM_L1_TIMER	12
+
+#define ATL1C_PCIE_L0S_L1_DISABLE 	0x01
+#define ATL1C_PCIE_PHY_RESET		0x02
+
+#define ATL1C_ASPM_L0s_ENABLE		0x0001
+#define ATL1C_ASPM_L1_ENABLE		0x0002
+
+#define AT_REGS_LEN	(75 * sizeof(u32))
+#define AT_EEPROM_LEN 	512
+
+#define ATL1C_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
+#define ATL1C_RFD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc)
+#define ATL1C_TPD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc)
+#define ATL1C_RRD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status)
+
+/* tpd word 1 bit 0:7 General Checksum task offload */
+#define TPD_L4HDR_OFFSET_MASK	0x00FF
+#define TPD_L4HDR_OFFSET_SHIFT	0
+
+/* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */
+#define TPD_TCPHDR_OFFSET_MASK	0x00FF
+#define TPD_TCPHDR_OFFSET_SHIFT	0
+
+/* tpd word 1 bit 0:7 Custom Checksum task offload */
+#define TPD_PLOADOFFSET_MASK	0x00FF
+#define TPD_PLOADOFFSET_SHIFT	0
+
+/* tpd word 1 bit 8:17 */
+#define TPD_CCSUM_EN_MASK	0x0001
+#define TPD_CCSUM_EN_SHIFT	8
+#define TPD_IP_CSUM_MASK	0x0001
+#define TPD_IP_CSUM_SHIFT	9
+#define TPD_TCP_CSUM_MASK	0x0001
+#define TPD_TCP_CSUM_SHIFT	10
+#define TPD_UDP_CSUM_MASK	0x0001
+#define TPD_UDP_CSUM_SHIFT	11
+#define TPD_LSO_EN_MASK		0x0001	/* TCP Large Send Offload */
+#define TPD_LSO_EN_SHIFT	12
+#define TPD_LSO_VER_MASK	0x0001
+#define TPD_LSO_VER_SHIFT	13 	/* 0 : ipv4; 1 : ipv4/ipv6 */
+#define TPD_CON_VTAG_MASK	0x0001
+#define TPD_CON_VTAG_SHIFT	14
+#define TPD_INS_VTAG_MASK	0x0001
+#define TPD_INS_VTAG_SHIFT	15
+#define TPD_IPV4_PACKET_MASK	0x0001  /* valid when LSO VER  is 1 */
+#define TPD_IPV4_PACKET_SHIFT	16
+#define TPD_ETH_TYPE_MASK	0x0001
+#define TPD_ETH_TYPE_SHIFT	17	/* 0 : 802.3 frame; 1 : Ethernet */
+
+/* tpd word 18:25 Custom Checksum task offload */
+#define TPD_CCSUM_OFFSET_MASK	0x00FF
+#define TPD_CCSUM_OFFSET_SHIFT	18
+#define TPD_CCSUM_EPAD_MASK	0x0001
+#define TPD_CCSUM_EPAD_SHIFT	30
+
+/* tpd word 18:30 Large Send task offload (IPv4/IPV6) */
+#define TPD_MSS_MASK            0x1FFF
+#define TPD_MSS_SHIFT		18
+
+#define TPD_EOP_MASK		0x0001
+#define TPD_EOP_SHIFT		31
+
+struct atl1c_tpd_desc {
+	__le16	buffer_len; /* include 4-byte CRC */
+	__le16	vlan_tag;
+	__le32	word1;
+	__le64	buffer_addr;
+};
+
+struct atl1c_tpd_ext_desc {
+	u32 reservd_0;
+	__le32 word1;
+	__le32 pkt_len;
+	u32 reservd_1;
+};
+/* rrs word 0 bit 0:31 */
+#define RRS_RX_CSUM_MASK	0xFFFF
+#define RRS_RX_CSUM_SHIFT	0
+#define RRS_RX_RFD_CNT_MASK	0x000F
+#define RRS_RX_RFD_CNT_SHIFT	16
+#define RRS_RX_RFD_INDEX_MASK	0x0FFF
+#define RRS_RX_RFD_INDEX_SHIFT	20
+
+/* rrs flag bit 0:16 */
+#define RRS_HEAD_LEN_MASK	0x00FF
+#define RRS_HEAD_LEN_SHIFT	0
+#define RRS_HDS_TYPE_MASK	0x0003
+#define RRS_HDS_TYPE_SHIFT	8
+#define RRS_CPU_NUM_MASK	0x0003
+#define	RRS_CPU_NUM_SHIFT	10
+#define RRS_HASH_FLG_MASK	0x000F
+#define RRS_HASH_FLG_SHIFT	12
+
+#define RRS_HDS_TYPE_HEAD	1
+#define RRS_HDS_TYPE_DATA	2
+
+#define RRS_IS_NO_HDS_TYPE(flag) \
+	(((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == 0)
+
+#define RRS_IS_HDS_HEAD(flag) \
+	(((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
+			RRS_HDS_TYPE_HEAD)
+
+#define RRS_IS_HDS_DATA(flag) \
+	(((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
+			RRS_HDS_TYPE_DATA)
+
+/* rrs word 3 bit 0:31 */
+#define RRS_PKT_SIZE_MASK	0x3FFF
+#define RRS_PKT_SIZE_SHIFT	0
+#define RRS_ERR_L4_CSUM_MASK	0x0001
+#define RRS_ERR_L4_CSUM_SHIFT	14
+#define RRS_ERR_IP_CSUM_MASK	0x0001
+#define RRS_ERR_IP_CSUM_SHIFT	15
+#define RRS_VLAN_INS_MASK	0x0001
+#define RRS_VLAN_INS_SHIFT	16
+#define RRS_PROT_ID_MASK	0x0007
+#define RRS_PROT_ID_SHIFT	17
+#define RRS_RX_ERR_SUM_MASK	0x0001
+#define RRS_RX_ERR_SUM_SHIFT	20
+#define RRS_RX_ERR_CRC_MASK	0x0001
+#define RRS_RX_ERR_CRC_SHIFT	21
+#define RRS_RX_ERR_FAE_MASK	0x0001
+#define RRS_RX_ERR_FAE_SHIFT	22
+#define RRS_RX_ERR_TRUNC_MASK	0x0001
+#define RRS_RX_ERR_TRUNC_SHIFT	23
+#define RRS_RX_ERR_RUNC_MASK	0x0001
+#define RRS_RX_ERR_RUNC_SHIFT	24
+#define RRS_RX_ERR_ICMP_MASK	0x0001
+#define RRS_RX_ERR_ICMP_SHIFT	25
+#define RRS_PACKET_BCAST_MASK	0x0001
+#define RRS_PACKET_BCAST_SHIFT	26
+#define RRS_PACKET_MCAST_MASK	0x0001
+#define RRS_PACKET_MCAST_SHIFT	27
+#define RRS_PACKET_TYPE_MASK	0x0001
+#define RRS_PACKET_TYPE_SHIFT	28
+#define RRS_FIFO_FULL_MASK	0x0001
+#define RRS_FIFO_FULL_SHIFT	29
+#define RRS_802_3_LEN_ERR_MASK 	0x0001
+#define RRS_802_3_LEN_ERR_SHIFT 30
+#define RRS_RXD_UPDATED_MASK	0x0001
+#define RRS_RXD_UPDATED_SHIFT	31
+
+#define RRS_ERR_L4_CSUM         0x00004000
+#define RRS_ERR_IP_CSUM         0x00008000
+#define RRS_VLAN_INS            0x00010000
+#define RRS_RX_ERR_SUM          0x00100000
+#define RRS_RX_ERR_CRC          0x00200000
+#define RRS_802_3_LEN_ERR	0x40000000
+#define RRS_RXD_UPDATED		0x80000000
+
+#define RRS_PACKET_TYPE_802_3  	1
+#define RRS_PACKET_TYPE_ETH	0
+#define RRS_PACKET_IS_ETH(word) \
+	(((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK == \
+			RRS_PACKET_TYPE_ETH)
+#define RRS_RXD_IS_VALID(word) \
+	((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1)
+
+#define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \
+	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1)
+#define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \
+	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6)
+
+struct atl1c_recv_ret_status {
+	__le32  word0;
+	__le32	rss_hash;
+	__le16	vlan_tag;
+	__le16	flag;
+	__le32	word3;
+};
+
+/* RFD desciptor */
+struct atl1c_rx_free_desc {
+	__le64	buffer_addr;
+};
+
+/* DMA Order Settings */
+enum atl1c_dma_order {
+	atl1c_dma_ord_in = 1,
+	atl1c_dma_ord_enh = 2,
+	atl1c_dma_ord_out = 4
+};
+
+enum atl1c_dma_rcb {
+	atl1c_rcb_64 = 0,
+	atl1c_rcb_128 = 1
+};
+
+enum atl1c_mac_speed {
+	atl1c_mac_speed_0 = 0,
+	atl1c_mac_speed_10_100 = 1,
+	atl1c_mac_speed_1000 = 2
+};
+
+enum atl1c_dma_req_block {
+	atl1c_dma_req_128 = 0,
+	atl1c_dma_req_256 = 1,
+	atl1c_dma_req_512 = 2,
+	atl1c_dma_req_1024 = 3,
+	atl1c_dma_req_2048 = 4,
+	atl1c_dma_req_4096 = 5
+};
+
+enum atl1c_rss_mode {
+	atl1c_rss_mode_disable = 0,
+	atl1c_rss_sig_que = 1,
+	atl1c_rss_mul_que_sig_int = 2,
+	atl1c_rss_mul_que_mul_int = 4,
+};
+
+enum atl1c_rss_type {
+	atl1c_rss_disable = 0,
+	atl1c_rss_ipv4 = 1,
+	atl1c_rss_ipv4_tcp = 2,
+	atl1c_rss_ipv6 = 4,
+	atl1c_rss_ipv6_tcp = 8
+};
+
+enum atl1c_nic_type {
+	athr_l1c = 0,
+	athr_l2c = 1,
+};
+
+enum atl1c_trans_queue {
+	atl1c_trans_normal = 0,
+	atl1c_trans_high = 1
+};
+
+struct atl1c_hw_stats {
+	/* rx */
+	unsigned long rx_ok;		/* The number of good packet received. */
+	unsigned long rx_bcast;		/* The number of good broadcast packet received. */
+	unsigned long rx_mcast;		/* The number of good multicast packet received. */
+	unsigned long rx_pause;		/* The number of Pause packet received. */
+	unsigned long rx_ctrl;		/* The number of Control packet received other than Pause frame. */
+	unsigned long rx_fcs_err;	/* The number of packets with bad FCS. */
+	unsigned long rx_len_err;	/* The number of packets with mismatch of length field and actual size. */
+	unsigned long rx_byte_cnt;	/* The number of bytes of good packet received. FCS is NOT included. */
+	unsigned long rx_runt;		/* The number of packets received that are less than 64 byte long and with good FCS. */
+	unsigned long rx_frag;		/* The number of packets received that are less than 64 byte long and with bad FCS. */
+	unsigned long rx_sz_64;		/* The number of good and bad packets received that are 64 byte long. */
+	unsigned long rx_sz_65_127;	/* The number of good and bad packets received that are between 65 and 127-byte long. */
+	unsigned long rx_sz_128_255;	/* The number of good and bad packets received that are between 128 and 255-byte long. */
+	unsigned long rx_sz_256_511;	/* The number of good and bad packets received that are between 256 and 511-byte long. */
+	unsigned long rx_sz_512_1023;	/* The number of good and bad packets received that are between 512 and 1023-byte long. */
+	unsigned long rx_sz_1024_1518;	/* The number of good and bad packets received that are between 1024 and 1518-byte long. */
+	unsigned long rx_sz_1519_max;	/* The number of good and bad packets received that are between 1519-byte and MTU. */
+	unsigned long rx_sz_ov;		/* The number of good and bad packets received that are more than MTU size truncated by Selene. */
+	unsigned long rx_rxf_ov;	/* The number of frame dropped due to occurrence of RX FIFO overflow. */
+	unsigned long rx_rrd_ov;	/* The number of frame dropped due to occurrence of RRD overflow. */
+	unsigned long rx_align_err;	/* Alignment Error */
+	unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
+	unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
+	unsigned long rx_err_addr;	/* The number of packets dropped due to address filtering. */
+
+	/* tx */
+	unsigned long tx_ok;		/* The number of good packet transmitted. */
+	unsigned long tx_bcast;		/* The number of good broadcast packet transmitted. */
+	unsigned long tx_mcast;		/* The number of good multicast packet transmitted. */
+	unsigned long tx_pause;		/* The number of Pause packet transmitted. */
+	unsigned long tx_exc_defer;	/* The number of packets transmitted with excessive deferral. */
+	unsigned long tx_ctrl;		/* The number of packets transmitted is a control frame, excluding Pause frame. */
+	unsigned long tx_defer;		/* The number of packets transmitted that is deferred. */
+	unsigned long tx_byte_cnt;	/* The number of bytes of data transmitted. FCS is NOT included. */
+	unsigned long tx_sz_64;		/* The number of good and bad packets transmitted that are 64 byte long. */
+	unsigned long tx_sz_65_127;	/* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
+	unsigned long tx_sz_128_255;	/* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
+	unsigned long tx_sz_256_511;	/* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
+	unsigned long tx_sz_512_1023;	/* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
+	unsigned long tx_sz_1024_1518;	/* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
+	unsigned long tx_sz_1519_max;	/* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
+	unsigned long tx_1_col;		/* The number of packets subsequently transmitted successfully with a single prior collision. */
+	unsigned long tx_2_col;		/* The number of packets subsequently transmitted successfully with multiple prior collisions. */
+	unsigned long tx_late_col;	/* The number of packets transmitted with late collisions. */
+	unsigned long tx_abort_col;	/* The number of transmit packets aborted due to excessive collisions. */
+	unsigned long tx_underrun;	/* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
+	unsigned long tx_rd_eop;	/* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
+	unsigned long tx_len_err;	/* The number of transmit packets with length field does NOT match the actual frame size. */
+	unsigned long tx_trunc;		/* The number of transmit packets truncated due to size exceeding MTU. */
+	unsigned long tx_bcast_byte;	/* The byte count of broadcast packet transmitted, excluding FCS. */
+	unsigned long tx_mcast_byte;	/* The byte count of multicast packet transmitted, excluding FCS. */
+};
+
+struct atl1c_hw {
+	u8 __iomem      *hw_addr;            /* inner register address */
+	struct atl1c_adapter *adapter;
+	enum atl1c_nic_type  nic_type;
+	enum atl1c_dma_order dma_order;
+	enum atl1c_dma_rcb   rcb_value;
+	enum atl1c_dma_req_block dmar_block;
+	enum atl1c_dma_req_block dmaw_block;
+
+	u16 device_id;
+	u16 vendor_id;
+	u16 subsystem_id;
+	u16 subsystem_vendor_id;
+	u8 revision_id;
+
+	u32 intr_mask;
+	u8 dmaw_dly_cnt;
+	u8 dmar_dly_cnt;
+
+	u8 preamble_len;
+	u16 max_frame_size;
+	u16 min_frame_size;
+
+	enum atl1c_mac_speed mac_speed;
+	bool mac_duplex;
+	bool hibernate;
+	u16 media_type;
+#define MEDIA_TYPE_AUTO_SENSOR  0
+#define MEDIA_TYPE_100M_FULL    1
+#define MEDIA_TYPE_100M_HALF    2
+#define MEDIA_TYPE_10M_FULL     3
+#define MEDIA_TYPE_10M_HALF     4
+
+	u16 autoneg_advertised;
+	u16 mii_autoneg_adv_reg;
+	u16 mii_1000t_ctrl_reg;
+
+	u16 tx_imt;	/* TX Interrupt Moderator timer ( 2us resolution) */
+	u16 rx_imt;	/* RX Interrupt Moderator timer ( 2us resolution) */
+	u16 ict;        /* Interrupt Clear timer (2us resolution) */
+	u16 ctrl_flags;
+#define ATL1C_INTR_CLEAR_ON_READ	0x0001
+#define ATL1C_INTR_MODRT_ENABLE	 	0x0002
+#define ATL1C_CMB_ENABLE		0x0004
+#define ATL1C_SMB_ENABLE		0x0010
+#define ATL1C_TXQ_MODE_ENHANCE		0x0020
+#define ATL1C_RX_IPV6_CHKSUM		0x0040
+#define ATL1C_ASPM_L0S_SUPPORT		0x0080
+#define ATL1C_ASPM_L1_SUPPORT		0x0100
+#define ATL1C_ASPM_CTRL_MON		0x0200
+#define ATL1C_HIB_DISABLE		0x0400
+#define ATL1C_LINK_CAP_1000M		0x0800
+#define ATL1C_FPGA_VERSION		0x8000
+	u16 cmb_tpd;
+	u16 cmb_rrd;
+	u16 cmb_rx_timer; /* 2us resolution */
+	u16 cmb_tx_timer;
+	u32 smb_timer;
+
+	u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
+			  interrupt request */
+	u16 tpd_thresh;
+	u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */
+	u8 rfd_burst;
+	enum atl1c_rss_type rss_type;
+	enum atl1c_rss_mode rss_mode;
+	u8 rss_hash_bits;
+	u32 base_cpu;
+	u32 indirect_tab;
+	u8 mac_addr[ETH_ALEN];
+	u8 perm_mac_addr[ETH_ALEN];
+
+	bool phy_configured;
+	bool re_autoneg;
+	bool emi_ca;
+};
+
+/*
+ * atl1c_ring_header represents a single, contiguous block of DMA space
+ * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
+ * message blocks (cmb, smb) described below
+ */
+struct atl1c_ring_header {
+	void *desc;		/* virtual address */
+	dma_addr_t dma;		/* physical address*/
+	unsigned int size;	/* length in bytes */
+};
+
+/*
+ * atl1c_buffer is wrapper around a pointer to a socket buffer
+ * so a DMA handle can be stored along with the skb
+ */
+struct atl1c_buffer {
+	struct sk_buff *skb;	/* socket buffer */
+	u16 length;		/* rx buffer length */
+	u16 state;		/* state of buffer */
+#define ATL1_BUFFER_FREE	0
+#define ATL1_BUFFER_BUSY	1
+	dma_addr_t dma;
+};
+
+/* transimit packet descriptor (tpd) ring */
+struct atl1c_tpd_ring {
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	u16 next_to_use; 	/* this is protectd by adapter->tx_lock */
+	atomic_t next_to_clean;
+	struct atl1c_buffer *buffer_info;
+};
+
+/* receive free descriptor (rfd) ring */
+struct atl1c_rfd_ring {
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	u16 next_to_use;
+	u16 next_to_clean;
+	struct atl1c_buffer *buffer_info;
+};
+
+/* receive return desciptor (rrd) ring */
+struct atl1c_rrd_ring {
+	void *desc;		/* descriptor ring virtual address */
+	dma_addr_t dma;		/* descriptor ring physical address */
+	u16 size;		/* descriptor ring length in bytes */
+	u16 count;		/* number of descriptors in the ring */
+	u16 next_to_use;
+	u16 next_to_clean;
+};
+
+struct atl1c_cmb {
+	void *cmb;
+	dma_addr_t dma;
+};
+
+struct atl1c_smb {
+	void *smb;
+	dma_addr_t dma;
+};
+
+/* board specific private data structure */
+struct atl1c_adapter {
+	struct net_device   *netdev;
+	struct pci_dev      *pdev;
+	struct vlan_group   *vlgrp;
+	struct napi_struct  napi;
+	struct atl1c_hw        hw;
+	struct atl1c_hw_stats  hw_stats;
+	struct net_device_stats net_stats;
+	struct mii_if_info  mii;    /* MII interface info */
+	u16 rx_buffer_len;
+
+	unsigned long flags;
+#define __AT_TESTING        0x0001
+#define __AT_RESETTING      0x0002
+#define __AT_DOWN           0x0003
+	u32 msg_enable;
+
+	bool have_msi;
+	u32 wol;
+	u16 link_speed;
+	u16 link_duplex;
+
+	spinlock_t mdio_lock;
+	spinlock_t tx_lock;
+	atomic_t irq_sem;
+
+	struct work_struct reset_task;
+	struct work_struct link_chg_task;
+	struct timer_list watchdog_timer;
+	struct timer_list phy_config_timer;
+
+	/* All Descriptor memory */
+	struct atl1c_ring_header ring_header;
+	struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE];
+	struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE];
+	struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE];
+	struct atl1c_cmb cmb;
+	struct atl1c_smb smb;
+	int num_rx_queues;
+	u32 bd_number;     /* board number;*/
+};
+
+#define AT_WRITE_REG(a, reg, value) ( \
+		writel((value), ((a)->hw_addr + reg)))
+
+#define AT_WRITE_FLUSH(a) (\
+		readl((a)->hw_addr))
+
+#define AT_READ_REG(a, reg, pdata) do {					\
+		if (unlikely((a)->hibernate)) {				\
+			readl((a)->hw_addr + reg);			\
+			*(u32 *)pdata = readl((a)->hw_addr + reg);	\
+		} else {						\
+			*(u32 *)pdata = readl((a)->hw_addr + reg);	\
+		}							\
+	} while (0)
+
+#define AT_WRITE_REGB(a, reg, value) (\
+		writeb((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGB(a, reg) (\
+		readb((a)->hw_addr + reg))
+
+#define AT_WRITE_REGW(a, reg, value) (\
+		writew((value), ((a)->hw_addr + reg)))
+
+#define AT_READ_REGW(a, reg) (\
+		readw((a)->hw_addr + reg))
+
+#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
+		writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
+
+#define AT_READ_REG_ARRAY(a, reg, offset) ( \
+		readl(((a)->hw_addr + reg) + ((offset) << 2)))
+
+extern char atl1c_driver_name[];
+extern char atl1c_driver_version[];
+
+extern int atl1c_up(struct atl1c_adapter *adapter);
+extern void atl1c_down(struct atl1c_adapter *adapter);
+extern void atl1c_reinit_locked(struct atl1c_adapter *adapter);
+extern s32 atl1c_reset_hw(struct atl1c_hw *hw);
+extern void atl1c_set_ethtool_ops(struct net_device *netdev);
+#endif /* _ATL1C_H_ */
diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c
new file mode 100644
index 0000000..45c5b73
--- /dev/null
+++ b/drivers/net/atl1c/atl1c_ethtool.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; 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.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+
+#include "atl1c.h"
+
+static int atl1c_get_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+
+	ecmd->supported = (SUPPORTED_10baseT_Half  |
+			   SUPPORTED_10baseT_Full  |
+			   SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_Autoneg       |
+			   SUPPORTED_TP);
+	if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M)
+		ecmd->supported |= SUPPORTED_1000baseT_Full;
+
+	ecmd->advertising = ADVERTISED_TP;
+
+	ecmd->advertising |= hw->autoneg_advertised;
+
+	ecmd->port = PORT_TP;
+	ecmd->phy_address = 0;
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	if (adapter->link_speed != SPEED_0) {
+		ecmd->speed = adapter->link_speed;
+		if (adapter->link_duplex == FULL_DUPLEX)
+			ecmd->duplex = DUPLEX_FULL;
+		else
+			ecmd->duplex = DUPLEX_HALF;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
+	}
+
+	ecmd->autoneg = AUTONEG_ENABLE;
+	return 0;
+}
+
+static int atl1c_set_settings(struct net_device *netdev,
+			      struct ethtool_cmd *ecmd)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	u16  autoneg_advertised;
+
+	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+		msleep(1);
+
+	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		autoneg_advertised = ADVERTISED_Autoneg;
+	} else {
+		if (ecmd->speed == SPEED_1000) {
+			if (ecmd->duplex != DUPLEX_FULL) {
+				if (netif_msg_link(adapter))
+					dev_warn(&adapter->pdev->dev,
+						"1000M half is invalid\n");
+				clear_bit(__AT_RESETTING, &adapter->flags);
+				return -EINVAL;
+			}
+			autoneg_advertised = ADVERTISED_1000baseT_Full;
+		} else if (ecmd->speed == SPEED_100) {
+			if (ecmd->duplex == DUPLEX_FULL)
+				autoneg_advertised = ADVERTISED_100baseT_Full;
+			else
+				autoneg_advertised = ADVERTISED_100baseT_Half;
+		} else {
+			if (ecmd->duplex == DUPLEX_FULL)
+				autoneg_advertised = ADVERTISED_10baseT_Full;
+			else
+				autoneg_advertised = ADVERTISED_10baseT_Half;
+		}
+	}
+
+	if (hw->autoneg_advertised != autoneg_advertised) {
+		hw->autoneg_advertised = autoneg_advertised;
+		if (atl1c_restart_autoneg(hw) != 0) {
+			if (netif_msg_link(adapter))
+				dev_warn(&adapter->pdev->dev,
+					"ethtool speed/duplex setting failed\n");
+			clear_bit(__AT_RESETTING, &adapter->flags);
+			return -EINVAL;
+		}
+	}
+	clear_bit(__AT_RESETTING, &adapter->flags);
+	return 0;
+}
+
+static u32 atl1c_get_tx_csum(struct net_device *netdev)
+{
+	return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static u32 atl1c_get_msglevel(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	return adapter->msg_enable;
+}
+
+static void atl1c_set_msglevel(struct net_device *netdev, u32 data)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	adapter->msg_enable = data;
+}
+
+static int atl1c_get_regs_len(struct net_device *netdev)
+{
+	return AT_REGS_LEN;
+}
+
+static void atl1c_get_regs(struct net_device *netdev,
+			   struct ethtool_regs *regs, void *p)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 *regs_buff = p;
+	u16 phy_data;
+
+	memset(p, 0, AT_REGS_LEN);
+
+	regs->version = 0;
+	AT_READ_REG(hw, REG_VPD_CAP, 		  p++);
+	AT_READ_REG(hw, REG_PM_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL,  p++);
+	AT_READ_REG(hw, REG_TWSI_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL,   p++);
+	AT_READ_REG(hw, REG_MASTER_CTRL, 	  p++);
+	AT_READ_REG(hw, REG_MANUAL_TIMER_INIT,    p++);
+	AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++);
+	AT_READ_REG(hw, REG_GPHY_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_LINK_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_IDLE_STATUS, 	  p++);
+	AT_READ_REG(hw, REG_MDIO_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_SERDES_LOCK, 	  p++);
+	AT_READ_REG(hw, REG_MAC_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_MAC_IPG_IFG, 	  p++);
+	AT_READ_REG(hw, REG_MAC_STA_ADDR, 	  p++);
+	AT_READ_REG(hw, REG_MAC_STA_ADDR+4, 	  p++);
+	AT_READ_REG(hw, REG_RX_HASH_TABLE, 	  p++);
+	AT_READ_REG(hw, REG_RX_HASH_TABLE+4, 	  p++);
+	AT_READ_REG(hw, REG_RXQ_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_TXQ_CTRL, 		  p++);
+	AT_READ_REG(hw, REG_MTU, 		  p++);
+	AT_READ_REG(hw, REG_WOL_CTRL, 		  p++);
+
+	atl1c_read_phy_reg(hw, MII_BMCR, &phy_data);
+	regs_buff[73] =	(u32) phy_data;
+	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+	regs_buff[74] = (u32) phy_data;
+}
+
+static int atl1c_get_eeprom_len(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	if (atl1c_check_eeprom_exist(&adapter->hw))
+		return AT_EEPROM_LEN;
+	else
+		return 0;
+}
+
+static int atl1c_get_eeprom(struct net_device *netdev,
+		struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 *eeprom_buff;
+	int first_dword, last_dword;
+	int ret_val = 0;
+	int i;
+
+	if (eeprom->len == 0)
+		return -EINVAL;
+
+	if (!atl1c_check_eeprom_exist(hw)) /* not exist */
+		return -EINVAL;
+
+	eeprom->magic = adapter->pdev->vendor |
+			(adapter->pdev->device << 16);
+
+	first_dword = eeprom->offset >> 2;
+	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
+
+	eeprom_buff = kmalloc(sizeof(u32) *
+			(last_dword - first_dword + 1), GFP_KERNEL);
+	if (eeprom_buff == NULL)
+		return -ENOMEM;
+
+	for (i = first_dword; i < last_dword; i++) {
+		if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
+			kfree(eeprom_buff);
+			return -EIO;
+		}
+	}
+
+	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
+			eeprom->len);
+	kfree(eeprom_buff);
+
+	return ret_val;
+	return 0;
+}
+
+static void atl1c_get_drvinfo(struct net_device *netdev,
+		struct ethtool_drvinfo *drvinfo)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	strncpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
+	strncpy(drvinfo->version, atl1c_driver_version,
+		sizeof(drvinfo->version));
+	strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+		sizeof(drvinfo->bus_info));
+	drvinfo->n_stats = 0;
+	drvinfo->testinfo_len = 0;
+	drvinfo->regdump_len = atl1c_get_regs_len(netdev);
+	drvinfo->eedump_len = atl1c_get_eeprom_len(netdev);
+}
+
+static void atl1c_get_wol(struct net_device *netdev,
+			  struct ethtool_wolinfo *wol)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_MAGIC | WAKE_PHY;
+	wol->wolopts = 0;
+
+	if (adapter->wol & AT_WUFC_EX)
+		wol->wolopts |= WAKE_UCAST;
+	if (adapter->wol & AT_WUFC_MC)
+		wol->wolopts |= WAKE_MCAST;
+	if (adapter->wol & AT_WUFC_BC)
+		wol->wolopts |= WAKE_BCAST;
+	if (adapter->wol & AT_WUFC_MAG)
+		wol->wolopts |= WAKE_MAGIC;
+	if (adapter->wol & AT_WUFC_LNKC)
+		wol->wolopts |= WAKE_PHY;
+
+	return;
+}
+
+static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
+			    WAKE_MCAST | WAKE_BCAST | WAKE_MCAST))
+		return -EOPNOTSUPP;
+	/* these settings will always override what we currently have */
+	adapter->wol = 0;
+
+	if (wol->wolopts & WAKE_MAGIC)
+		adapter->wol |= AT_WUFC_MAG;
+	if (wol->wolopts & WAKE_PHY)
+		adapter->wol |= AT_WUFC_LNKC;
+
+	return 0;
+}
+
+static int atl1c_nway_reset(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	if (netif_running(netdev))
+		atl1c_reinit_locked(adapter);
+	return 0;
+}
+
+static struct ethtool_ops atl1c_ethtool_ops = {
+	.get_settings           = atl1c_get_settings,
+	.set_settings           = atl1c_set_settings,
+	.get_drvinfo            = atl1c_get_drvinfo,
+	.get_regs_len           = atl1c_get_regs_len,
+	.get_regs               = atl1c_get_regs,
+	.get_wol                = atl1c_get_wol,
+	.set_wol                = atl1c_set_wol,
+	.get_msglevel           = atl1c_get_msglevel,
+	.set_msglevel           = atl1c_set_msglevel,
+	.nway_reset             = atl1c_nway_reset,
+	.get_link               = ethtool_op_get_link,
+	.get_eeprom_len         = atl1c_get_eeprom_len,
+	.get_eeprom             = atl1c_get_eeprom,
+	.get_tx_csum            = atl1c_get_tx_csum,
+	.get_sg                 = ethtool_op_get_sg,
+	.set_sg                 = ethtool_op_set_sg,
+};
+
+void atl1c_set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops);
+}
diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c
new file mode 100644
index 0000000..3e69b94
--- /dev/null
+++ b/drivers/net/atl1c/atl1c_hw.c
@@ -0,0 +1,527 @@
+/*
+ * Copyright(c) 2007 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; 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.
+ */
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+
+#include "atl1c.h"
+
+/*
+ * check_eeprom_exist
+ * return 1 if eeprom exist
+ */
+int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
+{
+	u32 data;
+
+	AT_READ_REG(hw, REG_TWSI_DEBUG, &data);
+	if (data & TWSI_DEBUG_DEV_EXIST)
+		return 1;
+
+	return 0;
+}
+
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
+{
+	u32 value;
+	/*
+	 * 00-0B-6A-F6-00-DC
+	 * 0:  6AF600DC 1: 000B
+	 * low dword
+	 */
+	value = (((u32)hw->mac_addr[2]) << 24) |
+		(((u32)hw->mac_addr[3]) << 16) |
+		(((u32)hw->mac_addr[4]) << 8)  |
+		(((u32)hw->mac_addr[5])) ;
+	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
+	/* hight dword */
+	value = (((u32)hw->mac_addr[0]) << 8) |
+		(((u32)hw->mac_addr[1])) ;
+	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
+}
+
+/*
+ * atl1c_get_permanent_address
+ * return 0 if get valid mac address,
+ */
+static int atl1c_get_permanent_address(struct atl1c_hw *hw)
+{
+	u32 addr[2];
+	u32 i;
+	u32 otp_ctrl_data;
+	u32 twsi_ctrl_data;
+	u8  eth_addr[ETH_ALEN];
+
+	/* init */
+	addr[0] = addr[1] = 0;
+	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
+	if (atl1c_check_eeprom_exist(hw)) {
+		/* Enable OTP CLK */
+		if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {
+			otp_ctrl_data |= OTP_CTRL_CLK_EN;
+			AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
+			AT_WRITE_FLUSH(hw);
+			msleep(1);
+		}
+
+		AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
+		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
+		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
+		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
+			msleep(10);
+			AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
+			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
+				break;
+		}
+		if (i >= AT_TWSI_EEPROM_TIMEOUT)
+			return -1;
+	}
+	/* Disable OTP_CLK */
+	if (otp_ctrl_data & OTP_CTRL_CLK_EN) {
+		otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
+		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
+		AT_WRITE_FLUSH(hw);
+		msleep(1);
+	}
+
+	/* maybe MAC-address is from BIOS */
+	AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
+	AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
+	*(u32 *) &eth_addr[2] = swab32(addr[0]);
+	*(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
+
+	if (is_valid_ether_addr(eth_addr)) {
+		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
+		return 0;
+	}
+
+	return -1;
+}
+
+bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)
+{
+	int i;
+	int ret = false;
+	u32 otp_ctrl_data;
+	u32 control;
+	u32 data;
+
+	if (offset & 3)
+		return ret; /* address do not align */
+
+	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
+	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
+		AT_WRITE_REG(hw, REG_OTP_CTRL,
+				(otp_ctrl_data | OTP_CTRL_CLK_EN));
+
+	AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0);
+	control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT;
+	AT_WRITE_REG(hw, REG_EEPROM_CTRL, control);
+
+	for (i = 0; i < 10; i++) {
+		udelay(100);
+		AT_READ_REG(hw, REG_EEPROM_CTRL, &control);
+		if (control & EEPROM_CTRL_RW)
+			break;
+	}
+	if (control & EEPROM_CTRL_RW) {
+		AT_READ_REG(hw, REG_EEPROM_CTRL, &data);
+		AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value);
+		data = data & 0xFFFF;
+		*p_value = swab32((data << 16) | (*p_value >> 16));
+		ret = true;
+	}
+	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
+		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
+
+	return ret;
+}
+/*
+ * Reads the adapter's MAC address from the EEPROM
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+int atl1c_read_mac_addr(struct atl1c_hw *hw)
+{
+	int err = 0;
+
+	err = atl1c_get_permanent_address(hw);
+	if (err)
+		random_ether_addr(hw->perm_mac_addr);
+
+	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
+	return 0;
+}
+
+/*
+ * atl1c_hash_mc_addr
+ *  purpose
+ *      set hash value for a multicast address
+ *      hash calcu processing :
+ *          1. calcu 32bit CRC for multicast address
+ *          2. reverse crc with MSB to LSB
+ */
+u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr)
+{
+	u32 crc32;
+	u32 value = 0;
+	int i;
+
+	crc32 = ether_crc_le(6, mc_addr);
+	for (i = 0; i < 32; i++)
+		value |= (((crc32 >> i) & 1) << (31 - i));
+
+	return value;
+}
+
+/*
+ * Sets the bit in the multicast table corresponding to the hash value.
+ * hw - Struct containing variables accessed by shared code
+ * hash_value - Multicast address hash value
+ */
+void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
+{
+	u32 hash_bit, hash_reg;
+	u32 mta;
+
+	/*
+	 * The HASH Table  is a register array of 2 32-bit registers.
+	 * It is treated like an array of 64 bits.  We want to set
+	 * bit BitArray[hash_value]. So we figure out what register
+	 * the bit is in, read it, OR in the new bit, then write
+	 * back the new value.  The register is determined by the
+	 * upper bit of the hash value and the bit within that
+	 * register are determined by the lower 5 bits of the value.
+	 */
+	hash_reg = (hash_value >> 31) & 0x1;
+	hash_bit = (hash_value >> 26) & 0x1F;
+
+	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
+
+	mta |= (1 << hash_bit);
+
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
+}
+
+/*
+ * Reads the value from a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to read
+ */
+int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
+{
+	u32 val;
+	int i;
+
+	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
+		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
+		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+	}
+	if (!(val & (MDIO_START | MDIO_BUSY))) {
+		*phy_data = (u16)val;
+		return 0;
+	}
+
+	return -1;
+}
+
+/*
+ * Writes a value to a PHY register
+ * hw - Struct containing variables accessed by shared code
+ * reg_addr - address of the PHY register to write
+ * data - data to write to the PHY
+ */
+int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
+{
+	int i;
+	u32 val;
+
+	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT   |
+	       (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
+	       MDIO_SUP_PREAMBLE | MDIO_START |
+	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
+
+	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
+
+	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
+		udelay(2);
+		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
+		if (!(val & (MDIO_START | MDIO_BUSY)))
+			break;
+	}
+
+	if (!(val & (MDIO_START | MDIO_BUSY)))
+		return 0;
+
+	return -1;
+}
+
+/*
+ * Configures PHY autoneg and flow control advertisement settings
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
+{
+	u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_SPEED_MASK;
+	u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
+				~GIGA_CR_1000T_SPEED_MASK;
+
+	if (hw->autoneg_advertised & ADVERTISED_10baseT_Half)
+		mii_adv_data |= ADVERTISE_10HALF;
+	if (hw->autoneg_advertised & ADVERTISED_10baseT_Full)
+		mii_adv_data |= ADVERTISE_10FULL;
+	if (hw->autoneg_advertised & ADVERTISED_100baseT_Half)
+		mii_adv_data |= ADVERTISE_100HALF;
+	if (hw->autoneg_advertised & ADVERTISED_100baseT_Full)
+		mii_adv_data |= ADVERTISE_100FULL;
+
+	if (hw->autoneg_advertised & ADVERTISED_Autoneg)
+		mii_adv_data |= ADVERTISE_10HALF  | ADVERTISE_10FULL |
+				ADVERTISE_100HALF | ADVERTISE_100FULL;
+
+	if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M) {
+		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half)
+			mii_giga_ctrl_data |= ADVERTISE_1000HALF;
+		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full)
+			mii_giga_ctrl_data |= ADVERTISE_1000FULL;
+		if (hw->autoneg_advertised & ADVERTISED_Autoneg)
+			mii_giga_ctrl_data |= ADVERTISE_1000HALF |
+					ADVERTISE_1000FULL;
+	}
+
+	if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
+	    atl1c_write_phy_reg(hw, MII_GIGA_CR, mii_giga_ctrl_data) != 0)
+		return -1;
+	return 0;
+}
+
+void atl1c_phy_disable(struct atl1c_hw *hw)
+{
+	AT_WRITE_REGW(hw, REG_GPHY_CTRL,
+			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
+}
+
+static void atl1c_phy_magic_data(struct atl1c_hw *hw)
+{
+	u16 data;
+
+	data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
+		((1 & ANA_INTERVAL_SEL_TIMER_MASK) <<
+		ANA_INTERVAL_SEL_TIMER_SHIFT);
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG |
+		ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL |
+		ANA_SERDES_EN_LCKDT;
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	data = (44 & ANA_LONG_CABLE_TH_100_MASK) |
+		((33 & ANA_SHORT_CABLE_TH_100_MASK) <<
+		ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM |
+		ANA_BP_SMALL_BW;
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) <<
+		ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
+		ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
+		ANA_IECHO_ADJ_0_SHIFT);
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) <<
+		ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE |
+		ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M;
+
+	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0);
+	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+	if (hw->ctrl_flags & ATL1C_HIB_DISABLE) {
+		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41);
+		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
+			return;
+		data &= ~ANA_TOP_PS_EN;
+		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+
+		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11);
+		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
+			return;
+		data &= ~ANA_PS_HIB_EN;
+		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
+	}
+}
+
+int atl1c_phy_reset(struct atl1c_hw *hw)
+{
+	struct atl1c_adapter *adapter = hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	u32 phy_ctrl_data = GPHY_CTRL_DEFAULT;
+	u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN;
+	int err;
+
+	if (hw->ctrl_flags & ATL1C_HIB_DISABLE)
+		phy_ctrl_data &= ~GPHY_CTRL_HIB_EN;
+
+	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
+	AT_WRITE_FLUSH(hw);
+	msleep(40);
+	phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
+	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
+	AT_WRITE_FLUSH(hw);
+	msleep(10);
+
+	/*Enable PHY LinkChange Interrupt */
+	err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
+	if (err) {
+		if (netif_msg_hw(adapter))
+			dev_err(&pdev->dev,
+				"Error enable PHY linkChange Interrupt\n");
+		return err;
+	}
+	if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
+		atl1c_phy_magic_data(hw);
+	return 0;
+}
+
+int atl1c_phy_init(struct atl1c_hw *hw)
+{
+	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	int ret_val;
+	u16 mii_bmcr_data = BMCR_RESET;
+	u16 phy_id1, phy_id2;
+
+	if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) ||
+		(atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) {
+			if (netif_msg_link(adapter))
+				dev_err(&pdev->dev, "Error get phy ID\n");
+		return -1;
+	}
+	switch (hw->media_type) {
+	case MEDIA_TYPE_AUTO_SENSOR:
+		ret_val = atl1c_phy_setup_adv(hw);
+		if (ret_val) {
+			if (netif_msg_link(adapter))
+				dev_err(&pdev->dev,
+					"Error Setting up Auto-Negotiation\n");
+			return ret_val;
+		}
+		mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
+		break;
+	case MEDIA_TYPE_100M_FULL:
+		mii_bmcr_data |= BMCR_SPEED_100 | BMCR_FULL_DUPLEX;
+		break;
+	case MEDIA_TYPE_100M_HALF:
+		mii_bmcr_data |= BMCR_SPEED_100;
+		break;
+	case MEDIA_TYPE_10M_FULL:
+		mii_bmcr_data |= BMCR_SPEED_10 | BMCR_FULL_DUPLEX;
+		break;
+	case MEDIA_TYPE_10M_HALF:
+		mii_bmcr_data |= BMCR_SPEED_10;
+		break;
+	default:
+		if (netif_msg_link(adapter))
+			dev_err(&pdev->dev, "Wrong Media type %d\n",
+				hw->media_type);
+		return -1;
+		break;
+	}
+
+	ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
+	if (ret_val)
+		return ret_val;
+	hw->phy_configured = true;
+
+	return 0;
+}
+
+/*
+ * Detects the current speed and duplex settings of the hardware.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * speed - Speed of the connection
+ * duplex - Duplex setting of the connection
+ */
+int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
+{
+	int err;
+	u16 phy_data;
+
+	/* Read   PHY Specific Status Register (17) */
+	err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data);
+	if (err)
+		return err;
+
+	if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED))
+		return -1;
+
+	switch (phy_data & GIGA_PSSR_SPEED) {
+	case GIGA_PSSR_1000MBS:
+		*speed = SPEED_1000;
+		break;
+	case GIGA_PSSR_100MBS:
+		*speed = SPEED_100;
+		break;
+	case  GIGA_PSSR_10MBS:
+		*speed = SPEED_10;
+		break;
+	default:
+		return -1;
+		break;
+	}
+
+	if (phy_data & GIGA_PSSR_DPLX)
+		*duplex = FULL_DUPLEX;
+	else
+		*duplex = HALF_DUPLEX;
+
+	return 0;
+}
+
+int atl1c_restart_autoneg(struct atl1c_hw *hw)
+{
+	int err = 0;
+	u16 mii_bmcr_data = BMCR_RESET;
+
+	err = atl1c_phy_setup_adv(hw);
+	if (err)
+		return err;
+	mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
+
+	return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
+}
diff --git a/drivers/net/atl1c/atl1c_hw.h b/drivers/net/atl1c/atl1c_hw.h
new file mode 100644
index 0000000..c2c738d
--- /dev/null
+++ b/drivers/net/atl1c/atl1c_hw.h
@@ -0,0 +1,859 @@
+/*
+ * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; 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 _ATL1C_HW_H_
+#define _ATL1C_HW_H_
+
+#include <linux/types.h>
+#include <linux/mii.h>
+
+struct atl1c_adapter;
+struct atl1c_hw;
+
+/* function prototype */
+void atl1c_phy_disable(struct atl1c_hw *hw);
+void atl1c_hw_set_mac_addr(struct atl1c_hw *hw);
+int atl1c_phy_reset(struct atl1c_hw *hw);
+int atl1c_read_mac_addr(struct atl1c_hw *hw);
+int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex);
+u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr);
+void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value);
+int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
+int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data);
+bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
+int atl1c_phy_init(struct atl1c_hw *hw);
+int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
+int atl1c_restart_autoneg(struct atl1c_hw *hw);
+
+/* register definition */
+#define REG_DEVICE_CAP              	0x5C
+#define DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
+#define DEVICE_CAP_MAX_PAYLOAD_SHIFT    0
+
+#define REG_DEVICE_CTRL			0x60
+#define DEVICE_CTRL_MAX_PAYLOAD_MASK    0x7
+#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT   5
+#define DEVICE_CTRL_MAX_RREQ_SZ_MASK    0x7
+#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT   12
+
+#define REG_LINK_CTRL			0x68
+#define LINK_CTRL_L0S_EN		0x01
+#define LINK_CTRL_L1_EN			0x02
+
+#define REG_VPD_CAP			0x6C
+#define VPD_CAP_ID_MASK                 0xff
+#define VPD_CAP_ID_SHIFT                0
+#define VPD_CAP_NEXT_PTR_MASK           0xFF
+#define VPD_CAP_NEXT_PTR_SHIFT          8
+#define VPD_CAP_VPD_ADDR_MASK           0x7FFF
+#define VPD_CAP_VPD_ADDR_SHIFT          16
+#define VPD_CAP_VPD_FLAG                0x80000000
+
+#define REG_VPD_DATA                	0x70
+
+#define REG_PCIE_UC_SEVERITY		0x10C
+#define PCIE_UC_SERVRITY_TRN		0x00000001
+#define PCIE_UC_SERVRITY_DLP		0x00000010
+#define PCIE_UC_SERVRITY_PSN_TLP	0x00001000
+#define PCIE_UC_SERVRITY_FCP		0x00002000
+#define PCIE_UC_SERVRITY_CPL_TO		0x00004000
+#define PCIE_UC_SERVRITY_CA		0x00008000
+#define PCIE_UC_SERVRITY_UC		0x00010000
+#define PCIE_UC_SERVRITY_ROV		0x00020000
+#define PCIE_UC_SERVRITY_MLFP		0x00040000
+#define PCIE_UC_SERVRITY_ECRC		0x00080000
+#define PCIE_UC_SERVRITY_UR		0x00100000
+
+#define REG_DEV_SERIALNUM_CTRL		0x200
+#define REG_DEV_MAC_SEL_MASK		0x0 /* 0:EUI; 1:MAC */
+#define REG_DEV_MAC_SEL_SHIFT		0
+#define REG_DEV_SERIAL_NUM_EN_MASK	0x1
+#define REG_DEV_SERIAL_NUM_EN_SHIFT	1
+
+#define REG_TWSI_CTRL               	0x218
+#define TWSI_CTRL_LD_OFFSET_MASK        0xFF
+#define TWSI_CTRL_LD_OFFSET_SHIFT       0
+#define TWSI_CTRL_LD_SLV_ADDR_MASK      0x7
+#define TWSI_CTRL_LD_SLV_ADDR_SHIFT     8
+#define TWSI_CTRL_SW_LDSTART            0x800
+#define TWSI_CTRL_HW_LDSTART            0x1000
+#define TWSI_CTRL_SMB_SLV_ADDR_MASK     0x7F
+#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15
+#define TWSI_CTRL_LD_EXIST              0x400000
+#define TWSI_CTRL_READ_FREQ_SEL_MASK    0x3
+#define TWSI_CTRL_READ_FREQ_SEL_SHIFT   23
+#define TWSI_CTRL_FREQ_SEL_100K         0
+#define TWSI_CTRL_FREQ_SEL_200K         1
+#define TWSI_CTRL_FREQ_SEL_300K         2
+#define TWSI_CTRL_FREQ_SEL_400K         3
+#define TWSI_CTRL_SMB_SLV_ADDR
+#define TWSI_CTRL_WRITE_FREQ_SEL_MASK   0x3
+#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT  24
+
+
+#define REG_PCIE_DEV_MISC_CTRL      	0x21C
+#define PCIE_DEV_MISC_EXT_PIPE     	0x2
+#define PCIE_DEV_MISC_RETRY_BUFDIS 	0x1
+#define PCIE_DEV_MISC_SPIROM_EXIST 	0x4
+#define PCIE_DEV_MISC_SERDES_ENDIAN    	0x8
+#define PCIE_DEV_MISC_SERDES_SEL_DIN   	0x10
+
+#define REG_PCIE_PHYMISC	    	0x1000
+#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
+
+#define REG_TWSI_DEBUG			0x1108
+#define TWSI_DEBUG_DEV_EXIST		0x20000000
+
+#define REG_EEPROM_CTRL			0x12C0
+#define EEPROM_CTRL_DATA_HI_MASK	0xFFFF
+#define EEPROM_CTRL_DATA_HI_SHIFT	0
+#define EEPROM_CTRL_ADDR_MASK		0x3FF
+#define EEPROM_CTRL_ADDR_SHIFT		16
+#define EEPROM_CTRL_ACK			0x40000000
+#define EEPROM_CTRL_RW			0x80000000
+
+#define REG_EEPROM_DATA_LO		0x12C4
+
+#define REG_OTP_CTRL			0x12F0
+#define OTP_CTRL_CLK_EN			0x0002
+
+#define REG_PM_CTRL			0x12F8
+#define PM_CTRL_SDES_EN			0x00000001
+#define PM_CTRL_RBER_EN			0x00000002
+#define PM_CTRL_CLK_REQ_EN		0x00000004
+#define PM_CTRL_ASPM_L1_EN		0x00000008
+#define PM_CTRL_SERDES_L1_EN		0x00000010
+#define PM_CTRL_SERDES_PLL_L1_EN	0x00000020
+#define PM_CTRL_SERDES_PD_EX_L1		0x00000040
+#define PM_CTRL_SERDES_BUDS_RX_L1_EN	0x00000080
+#define PM_CTRL_L0S_ENTRY_TIMER_MASK	0xF
+#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT	8
+#define PM_CTRL_ASPM_L0S_EN		0x00001000
+#define PM_CTRL_CLK_SWH_L1		0x00002000
+#define PM_CTRL_CLK_PWM_VER1_1		0x00004000
+#define PM_CTRL_PCIE_RECV		0x00008000
+#define PM_CTRL_L1_ENTRY_TIMER_MASK	0xF
+#define PM_CTRL_L1_ENTRY_TIMER_SHIFT	16
+#define PM_CTRL_PM_REQ_TIMER_MASK	0xF
+#define PM_CTRL_PM_REQ_TIMER_SHIFT	20
+#define PM_CTRL_LCKDET_TIMER_MASK	0x3F
+#define PM_CTRL_LCKDET_TIMER_SHIFT	24
+#define PM_CTRL_MAC_ASPM_CHK		0x40000000
+#define PM_CTRL_HOTRST			0x80000000
+
+/* Selene Master Control Register */
+#define REG_MASTER_CTRL			0x1400
+#define MASTER_CTRL_SOFT_RST            0x1
+#define MASTER_CTRL_TEST_MODE_MASK	0x3
+#define MASTER_CTRL_TEST_MODE_SHIFT	2
+#define MASTER_CTRL_BERT_START		0x10
+#define MASTER_CTRL_MTIMER_EN           0x100
+#define MASTER_CTRL_MANUAL_INT          0x200
+#define MASTER_CTRL_TX_ITIMER_EN	0x400
+#define MASTER_CTRL_RX_ITIMER_EN	0x800
+#define MASTER_CTRL_CLK_SEL_DIS		0x1000
+#define MASTER_CTRL_CLK_SWH_MODE	0x2000
+#define MASTER_CTRL_INT_RDCLR		0x4000
+#define MASTER_CTRL_REV_NUM_SHIFT	16
+#define MASTER_CTRL_REV_NUM_MASK	0xff
+#define MASTER_CTRL_DEV_ID_SHIFT	24
+#define MASTER_CTRL_DEV_ID_MASK		0x7f
+#define MASTER_CTRL_OTP_SEL		0x80000000
+
+/* Timer Initial Value Register */
+#define REG_MANUAL_TIMER_INIT       	0x1404
+
+/* IRQ ModeratorTimer Initial Value Register */
+#define REG_IRQ_MODRT_TIMER_INIT     	0x1408
+#define IRQ_MODRT_TIMER_MASK		0xffff
+#define IRQ_MODRT_TX_TIMER_SHIFT    	0
+#define IRQ_MODRT_RX_TIMER_SHIFT	16
+
+#define REG_GPHY_CTRL               	0x140C
+#define GPHY_CTRL_EXT_RESET         	0x1
+#define GPHY_CTRL_RTL_MODE		0x2
+#define GPHY_CTRL_LED_MODE		0x4
+#define GPHY_CTRL_ANEG_NOW		0x8
+#define GPHY_CTRL_REV_ANEG		0x10
+#define GPHY_CTRL_GATE_25M_EN       	0x20
+#define GPHY_CTRL_LPW_EXIT          	0x40
+#define GPHY_CTRL_PHY_IDDQ          	0x80
+#define GPHY_CTRL_PHY_IDDQ_DIS      	0x100
+#define GPHY_CTRL_GIGA_DIS		0x200
+#define GPHY_CTRL_HIB_EN            	0x400
+#define GPHY_CTRL_HIB_PULSE         	0x800
+#define GPHY_CTRL_SEL_ANA_RST       	0x1000
+#define GPHY_CTRL_PHY_PLL_ON        	0x2000
+#define GPHY_CTRL_PWDOWN_HW		0x4000
+#define GPHY_CTRL_PHY_PLL_BYPASS	0x8000
+
+#define GPHY_CTRL_DEFAULT (		 \
+		GPHY_CTRL_SEL_ANA_RST	|\
+		GPHY_CTRL_HIB_PULSE	|\
+		GPHY_CTRL_HIB_EN)
+
+#define GPHY_CTRL_PW_WOL_DIS (		 \
+		GPHY_CTRL_SEL_ANA_RST	|\
+		GPHY_CTRL_HIB_PULSE	|\
+		GPHY_CTRL_HIB_EN	|\
+		GPHY_CTRL_PWDOWN_HW	|\
+		GPHY_CTRL_PHY_IDDQ)
+
+/* Block IDLE Status Register */
+#define REG_IDLE_STATUS  		0x1410
+#define IDLE_STATUS_MASK		0x00FF
+#define IDLE_STATUS_RXMAC_NO_IDLE      	0x1
+#define IDLE_STATUS_TXMAC_NO_IDLE      	0x2
+#define IDLE_STATUS_RXQ_NO_IDLE        	0x4
+#define IDLE_STATUS_TXQ_NO_IDLE        	0x8
+#define IDLE_STATUS_DMAR_NO_IDLE       	0x10
+#define IDLE_STATUS_DMAW_NO_IDLE       	0x20
+#define IDLE_STATUS_SMB_NO_IDLE        	0x40
+#define IDLE_STATUS_CMB_NO_IDLE        	0x80
+
+/* MDIO Control Register */
+#define REG_MDIO_CTRL           	0x1414
+#define MDIO_DATA_MASK          	0xffff  /* On MDIO write, the 16-bit
+						 * control data to write to PHY
+						 * MII management register */
+#define MDIO_DATA_SHIFT         	0       /* On MDIO read, the 16-bit
+						 * status data that was read
+						 * from the PHY MII management register */
+#define MDIO_REG_ADDR_MASK      	0x1f    /* MDIO register address */
+#define MDIO_REG_ADDR_SHIFT     	16
+#define MDIO_RW                 	0x200000  /* 1: read, 0: write */
+#define MDIO_SUP_PREAMBLE       	0x400000  /* Suppress preamble */
+#define MDIO_START              	0x800000  /* Write 1 to initiate the MDIO
+						   * master. And this bit is self
+						   * cleared after one cycle */
+#define MDIO_CLK_SEL_SHIFT      	24
+#define MDIO_CLK_25_4           	0
+#define MDIO_CLK_25_6           	2
+#define MDIO_CLK_25_8           	3
+#define MDIO_CLK_25_10          	4
+#define MDIO_CLK_25_14          	5
+#define MDIO_CLK_25_20          	6
+#define MDIO_CLK_25_28          	7
+#define MDIO_BUSY               	0x8000000
+#define MDIO_AP_EN              	0x10000000
+#define MDIO_WAIT_TIMES         	10
+
+/* MII PHY Status Register */
+#define REG_PHY_STATUS           	0x1418
+#define PHY_GENERAL_STATUS_MASK		0xFFFF
+#define PHY_STATUS_RECV_ENABLE		0x0001
+#define PHY_OE_PWSP_STATUS_MASK		0x07FF
+#define PHY_OE_PWSP_STATUS_SHIFT	16
+#define PHY_STATUS_LPW_STATE		0x80000000
+/* BIST Control and Status Register0 (for the Packet Memory) */
+#define REG_BIST0_CTRL              	0x141c
+#define BIST0_NOW                   	0x1
+#define BIST0_SRAM_FAIL             	0x2 /* 1: The SRAM failure is
+					     * un-repairable  because
+					     * it has address decoder
+					     * failure or more than 1 cell
+					     * stuck-to-x failure */
+#define BIST0_FUSE_FLAG             	0x4
+
+/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
+#define REG_BIST1_CTRL			0x1420
+#define BIST1_NOW                   	0x1
+#define BIST1_SRAM_FAIL             	0x2
+#define BIST1_FUSE_FLAG             	0x4
+
+/* SerDes Lock Detect Control and Status Register */
+#define REG_SERDES_LOCK            	0x1424
+#define SERDES_LOCK_DETECT          	0x1  /* SerDes lock detected. This signal
+					      * comes from Analog SerDes */
+#define SERDES_LOCK_DETECT_EN       	0x2  /* 1: Enable SerDes Lock detect function */
+
+/* MAC Control Register  */
+#define REG_MAC_CTRL         		0x1480
+#define MAC_CTRL_TX_EN			0x1
+#define MAC_CTRL_RX_EN			0x2
+#define MAC_CTRL_TX_FLOW		0x4
+#define MAC_CTRL_RX_FLOW            	0x8
+#define MAC_CTRL_LOOPBACK          	0x10
+#define MAC_CTRL_DUPLX              	0x20
+#define MAC_CTRL_ADD_CRC            	0x40
+#define MAC_CTRL_PAD                	0x80
+#define MAC_CTRL_LENCHK             	0x100
+#define MAC_CTRL_HUGE_EN            	0x200
+#define MAC_CTRL_PRMLEN_SHIFT       	10
+#define MAC_CTRL_PRMLEN_MASK        	0xf
+#define MAC_CTRL_RMV_VLAN           	0x4000
+#define MAC_CTRL_PROMIS_EN          	0x8000
+#define MAC_CTRL_TX_PAUSE           	0x10000
+#define MAC_CTRL_SCNT               	0x20000
+#define MAC_CTRL_SRST_TX            	0x40000
+#define MAC_CTRL_TX_SIMURST         	0x80000
+#define MAC_CTRL_SPEED_SHIFT        	20
+#define MAC_CTRL_SPEED_MASK         	0x3
+#define MAC_CTRL_DBG_TX_BKPRESURE   	0x400000
+#define MAC_CTRL_TX_HUGE            	0x800000
+#define MAC_CTRL_RX_CHKSUM_EN       	0x1000000
+#define MAC_CTRL_MC_ALL_EN          	0x2000000
+#define MAC_CTRL_BC_EN              	0x4000000
+#define MAC_CTRL_DBG                	0x8000000
+#define MAC_CTRL_SINGLE_PAUSE_EN	0x10000000
+
+/* MAC IPG/IFG Control Register  */
+#define REG_MAC_IPG_IFG             	0x1484
+#define MAC_IPG_IFG_IPGT_SHIFT      	0 	/* Desired back to back
+						 * inter-packet gap. The
+						 * default is 96-bit time */
+#define MAC_IPG_IFG_IPGT_MASK       	0x7f
+#define MAC_IPG_IFG_MIFG_SHIFT      	8       /* Minimum number of IFG to
+						 * enforce in between RX frames */
+#define MAC_IPG_IFG_MIFG_MASK       	0xff  	/* Frame gap below such IFP is dropped */
+#define MAC_IPG_IFG_IPGR1_SHIFT     	16   	/* 64bit Carrier-Sense window */
+#define MAC_IPG_IFG_IPGR1_MASK      	0x7f
+#define MAC_IPG_IFG_IPGR2_SHIFT     	24    	/* 96-bit IPG window */
+#define MAC_IPG_IFG_IPGR2_MASK      	0x7f
+
+/* MAC STATION ADDRESS  */
+#define REG_MAC_STA_ADDR		0x1488
+
+/* Hash table for multicast address */
+#define REG_RX_HASH_TABLE		0x1490
+
+/* MAC Half-Duplex Control Register */
+#define REG_MAC_HALF_DUPLX_CTRL     	0x1498
+#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT  0      /* Collision Window */
+#define MAC_HALF_DUPLX_CTRL_LCOL_MASK   0x3ff
+#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12
+#define MAC_HALF_DUPLX_CTRL_RETRY_MASK  0xf
+#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN  0x10000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_C   0x20000
+#define MAC_HALF_DUPLX_CTRL_NO_BACK_P   0x40000 /* No back-off on backpressure,
+						 * immediately start the
+						 * transmission after back pressure */
+#define MAC_HALF_DUPLX_CTRL_ABEBE        0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT  20      /* Maximum binary exponential number */
+#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK   0xf
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24      /* IPG to start JAM for collision based flow control in half-duplex */
+#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK  0xf     /* mode. In unit of 8-bit time */
+
+/* Maximum Frame Length Control Register   */
+#define REG_MTU                     	0x149c
+
+/* Wake-On-Lan control register */
+#define REG_WOL_CTRL                	0x14a0
+#define WOL_PATTERN_EN              	0x00000001
+#define WOL_PATTERN_PME_EN              0x00000002
+#define WOL_MAGIC_EN                    0x00000004
+#define WOL_MAGIC_PME_EN                0x00000008
+#define WOL_LINK_CHG_EN                 0x00000010
+#define WOL_LINK_CHG_PME_EN             0x00000020
+#define WOL_PATTERN_ST                  0x00000100
+#define WOL_MAGIC_ST                    0x00000200
+#define WOL_LINKCHG_ST                  0x00000400
+#define WOL_CLK_SWITCH_EN               0x00008000
+#define WOL_PT0_EN                      0x00010000
+#define WOL_PT1_EN                      0x00020000
+#define WOL_PT2_EN                      0x00040000
+#define WOL_PT3_EN                      0x00080000
+#define WOL_PT4_EN                      0x00100000
+#define WOL_PT5_EN                      0x00200000
+#define WOL_PT6_EN                      0x00400000
+
+/* WOL Length ( 2 DWORD ) */
+#define REG_WOL_PATTERN_LEN         	0x14a4
+#define WOL_PT_LEN_MASK                 0x7f
+#define WOL_PT0_LEN_SHIFT               0
+#define WOL_PT1_LEN_SHIFT               8
+#define WOL_PT2_LEN_SHIFT               16
+#define WOL_PT3_LEN_SHIFT               24
+#define WOL_PT4_LEN_SHIFT               0
+#define WOL_PT5_LEN_SHIFT               8
+#define WOL_PT6_LEN_SHIFT               16
+
+/* Internal SRAM Partition Register */
+#define RFDX_HEAD_ADDR_MASK		0x03FF
+#define RFDX_HARD_ADDR_SHIFT		0
+#define RFDX_TAIL_ADDR_MASK		0x03FF
+#define RFDX_TAIL_ADDR_SHIFT            16
+
+#define REG_SRAM_RFD0_INFO		0x1500
+#define REG_SRAM_RFD1_INFO		0x1504
+#define REG_SRAM_RFD2_INFO		0x1508
+#define	REG_SRAM_RFD3_INFO		0x150C
+
+#define REG_RFD_NIC_LEN			0x1510 /* In 8-bytes */
+#define RFD_NIC_LEN_MASK		0x03FF
+
+#define REG_SRAM_TRD_ADDR           	0x1518
+#define TPD_HEAD_ADDR_MASK		0x03FF
+#define TPD_HEAD_ADDR_SHIFT		0
+#define TPD_TAIL_ADDR_MASK		0x03FF
+#define TPD_TAIL_ADDR_SHIFT		16
+
+#define REG_SRAM_TRD_LEN            	0x151C /* In 8-bytes */
+#define TPD_NIC_LEN_MASK		0x03FF
+
+#define REG_SRAM_RXF_ADDR          	0x1520
+#define REG_SRAM_RXF_LEN            	0x1524
+#define REG_SRAM_TXF_ADDR           	0x1528
+#define REG_SRAM_TXF_LEN            	0x152C
+#define REG_SRAM_TCPH_ADDR          	0x1530
+#define REG_SRAM_PKTH_ADDR          	0x1532
+
+/*
+ * Load Ptr Register
+ * Software sets this bit after the initialization of the head and tail */
+#define REG_LOAD_PTR                	0x1534
+
+/*
+ * addresses of all descriptors, as well as the following descriptor
+ * control register, which triggers each function block to load the head
+ * pointer to prepare for the operation. This bit is then self-cleared
+ * after one cycle.
+ */
+#define REG_RX_BASE_ADDR_HI		0x1540
+#define REG_TX_BASE_ADDR_HI		0x1544
+#define REG_SMB_BASE_ADDR_HI		0x1548
+#define REG_SMB_BASE_ADDR_LO		0x154C
+#define REG_RFD0_HEAD_ADDR_LO		0x1550
+#define REG_RFD1_HEAD_ADDR_LO		0x1554
+#define REG_RFD2_HEAD_ADDR_LO		0x1558
+#define REG_RFD3_HEAD_ADDR_LO		0x155C
+#define REG_RFD_RING_SIZE		0x1560
+#define RFD_RING_SIZE_MASK		0x0FFF
+#define REG_RX_BUF_SIZE			0x1564
+#define RX_BUF_SIZE_MASK		0xFFFF
+#define REG_RRD0_HEAD_ADDR_LO		0x1568
+#define REG_RRD1_HEAD_ADDR_LO		0x156C
+#define REG_RRD2_HEAD_ADDR_LO		0x1570
+#define REG_RRD3_HEAD_ADDR_LO		0x1574
+#define REG_RRD_RING_SIZE		0x1578
+#define RRD_RING_SIZE_MASK		0x0FFF
+#define REG_HTPD_HEAD_ADDR_LO		0x157C
+#define REG_NTPD_HEAD_ADDR_LO		0x1580
+#define REG_TPD_RING_SIZE		0x1584
+#define TPD_RING_SIZE_MASK		0xFFFF
+#define REG_CMB_BASE_ADDR_LO		0x1588
+
+/* RSS about */
+#define REG_RSS_KEY0                    0x14B0
+#define REG_RSS_KEY1                    0x14B4
+#define REG_RSS_KEY2                    0x14B8
+#define REG_RSS_KEY3                    0x14BC
+#define REG_RSS_KEY4                    0x14C0
+#define REG_RSS_KEY5                    0x14C4
+#define REG_RSS_KEY6                    0x14C8
+#define REG_RSS_KEY7                    0x14CC
+#define REG_RSS_KEY8                    0x14D0
+#define REG_RSS_KEY9                    0x14D4
+#define REG_IDT_TABLE0                	0x14E0
+#define REG_IDT_TABLE1                  0x14E4
+#define REG_IDT_TABLE2                  0x14E8
+#define REG_IDT_TABLE3                  0x14EC
+#define REG_IDT_TABLE4                  0x14F0
+#define REG_IDT_TABLE5                  0x14F4
+#define REG_IDT_TABLE6                  0x14F8
+#define REG_IDT_TABLE7                  0x14FC
+#define REG_IDT_TABLE                   REG_IDT_TABLE0
+#define REG_RSS_HASH_VALUE              0x15B0
+#define REG_RSS_HASH_FLAG               0x15B4
+#define REG_BASE_CPU_NUMBER             0x15B8
+
+/* TXQ Control Register */
+#define REG_TXQ_CTRL                	0x1590
+#define	TXQ_NUM_TPD_BURST_MASK     	0xF
+#define TXQ_NUM_TPD_BURST_SHIFT    	0
+#define TXQ_CTRL_IP_OPTION_EN		0x10
+#define TXQ_CTRL_EN                     0x20
+#define TXQ_CTRL_ENH_MODE               0x40
+#define TXQ_CTRL_LS_8023_EN		0x80
+#define TXQ_TXF_BURST_NUM_SHIFT    	16
+#define TXQ_TXF_BURST_NUM_MASK     	0xFFFF
+
+/* Jumbo packet Threshold for task offload */
+#define REG_TX_TSO_OFFLOAD_THRESH	0x1594 /* In 8-bytes */
+#define TX_TSO_OFFLOAD_THRESH_MASK	0x07FF
+
+#define	REG_TXF_WATER_MARK		0x1598 /* In 8-bytes */
+#define TXF_WATER_MARK_MASK		0x0FFF
+#define TXF_LOW_WATER_MARK_SHIFT	0
+#define TXF_HIGH_WATER_MARK_SHIFT 	16
+#define TXQ_CTRL_BURST_MODE_EN		0x80000000
+
+#define REG_THRUPUT_MON_CTRL		0x159C
+#define THRUPUT_MON_RATE_MASK		0x3
+#define THRUPUT_MON_RATE_SHIFT		0
+#define THRUPUT_MON_EN			0x80
+
+/* RXQ Control Register */
+#define REG_RXQ_CTRL                	0x15A0
+#define ASPM_THRUPUT_LIMIT_MASK		0x3
+#define ASPM_THRUPUT_LIMIT_SHIFT	0
+#define ASPM_THRUPUT_LIMIT_NO		0x00
+#define ASPM_THRUPUT_LIMIT_1M		0x01
+#define ASPM_THRUPUT_LIMIT_10M		0x02
+#define ASPM_THRUPUT_LIMIT_100M		0x04
+#define RXQ1_CTRL_EN			0x10
+#define RXQ2_CTRL_EN			0x20
+#define RXQ3_CTRL_EN			0x40
+#define IPV6_CHKSUM_CTRL_EN		0x80
+#define RSS_HASH_BITS_MASK		0x00FF
+#define RSS_HASH_BITS_SHIFT		8
+#define RSS_HASH_IPV4			0x10000
+#define RSS_HASH_IPV4_TCP		0x20000
+#define RSS_HASH_IPV6			0x40000
+#define RSS_HASH_IPV6_TCP		0x80000
+#define RXQ_RFD_BURST_NUM_MASK		0x003F
+#define RXQ_RFD_BURST_NUM_SHIFT		20
+#define RSS_MODE_MASK			0x0003
+#define RSS_MODE_SHIFT			26
+#define RSS_NIP_QUEUE_SEL_MASK		0x1
+#define RSS_NIP_QUEUE_SEL_SHIFT		28
+#define RRS_HASH_CTRL_EN		0x20000000
+#define RX_CUT_THRU_EN			0x40000000
+#define RXQ_CTRL_EN			0x80000000
+
+#define REG_RFD_FREE_THRESH		0x15A4
+#define RFD_FREE_THRESH_MASK		0x003F
+#define RFD_FREE_HI_THRESH_SHIFT	0
+#define RFD_FREE_LO_THRESH_SHIFT	6
+
+/* RXF flow control register */
+#define REG_RXQ_RXF_PAUSE_THRESH    	0x15A8
+#define RXQ_RXF_PAUSE_TH_HI_SHIFT       0
+#define RXQ_RXF_PAUSE_TH_HI_MASK        0x0FFF
+#define RXQ_RXF_PAUSE_TH_LO_SHIFT       16
+#define RXQ_RXF_PAUSE_TH_LO_MASK        0x0FFF
+
+#define REG_RXD_DMA_CTRL		0x15AC
+#define RXD_DMA_THRESH_MASK		0x0FFF	/* In 8-bytes */
+#define RXD_DMA_THRESH_SHIFT		0
+#define RXD_DMA_DOWN_TIMER_MASK		0xFFFF
+#define RXD_DMA_DOWN_TIMER_SHIFT	16
+
+/* DMA Engine Control Register */
+#define REG_DMA_CTRL                	0x15C0
+#define DMA_CTRL_DMAR_IN_ORDER          0x1
+#define DMA_CTRL_DMAR_ENH_ORDER         0x2
+#define DMA_CTRL_DMAR_OUT_ORDER         0x4
+#define DMA_CTRL_RCB_VALUE              0x8
+#define DMA_CTRL_DMAR_BURST_LEN_MASK    0x0007
+#define DMA_CTRL_DMAR_BURST_LEN_SHIFT   4
+#define DMA_CTRL_DMAW_BURST_LEN_MASK    0x0007
+#define DMA_CTRL_DMAW_BURST_LEN_SHIFT   7
+#define DMA_CTRL_DMAR_REQ_PRI           0x400
+#define DMA_CTRL_DMAR_DLY_CNT_MASK      0x001F
+#define DMA_CTRL_DMAR_DLY_CNT_SHIFT     11
+#define DMA_CTRL_DMAW_DLY_CNT_MASK      0x000F
+#define DMA_CTRL_DMAW_DLY_CNT_SHIFT     16
+#define DMA_CTRL_CMB_EN               	0x100000
+#define DMA_CTRL_SMB_EN			0x200000
+#define DMA_CTRL_CMB_NOW		0x400000
+#define MAC_CTRL_SMB_DIS		0x1000000
+#define DMA_CTRL_SMB_NOW		0x80000000
+
+/* CMB/SMB Control Register */
+#define REG_SMB_STAT_TIMER		0x15C4	/* 2us resolution */
+#define SMB_STAT_TIMER_MASK		0xFFFFFF
+#define REG_CMB_TPD_THRESH		0x15C8
+#define CMB_TPD_THRESH_MASK		0xFFFF
+#define REG_CMB_TX_TIMER		0x15CC	/* 2us resolution */
+#define CMB_TX_TIMER_MASK		0xFFFF
+
+/* Mail box */
+#define MB_RFDX_PROD_IDX_MASK		0xFFFF
+#define REG_MB_RFD0_PROD_IDX		0x15E0
+#define REG_MB_RFD1_PROD_IDX		0x15E4
+#define REG_MB_RFD2_PROD_IDX		0x15E8
+#define REG_MB_RFD3_PROD_IDX		0x15EC
+
+#define MB_PRIO_PROD_IDX_MASK		0xFFFF
+#define REG_MB_PRIO_PROD_IDX		0x15F0
+#define MB_HTPD_PROD_IDX_SHIFT		0
+#define MB_NTPD_PROD_IDX_SHIFT		16
+
+#define MB_PRIO_CONS_IDX_MASK		0xFFFF
+#define REG_MB_PRIO_CONS_IDX		0x15F4
+#define MB_HTPD_CONS_IDX_SHIFT		0
+#define MB_NTPD_CONS_IDX_SHIFT		16
+
+#define REG_MB_RFD01_CONS_IDX		0x15F8
+#define MB_RFD0_CONS_IDX_MASK		0x0000FFFF
+#define MB_RFD1_CONS_IDX_MASK		0xFFFF0000
+#define REG_MB_RFD23_CONS_IDX		0x15FC
+#define MB_RFD2_CONS_IDX_MASK		0x0000FFFF
+#define MB_RFD3_CONS_IDX_MASK		0xFFFF0000
+
+/* Interrupt Status Register */
+#define REG_ISR    			0x1600
+#define ISR_SMB				0x00000001
+#define ISR_TIMER			0x00000002
+/*
+ * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
+ * in Table 51 Selene Master Control Register (Offset 0x1400).
+ */
+#define ISR_MANUAL         		0x00000004
+#define ISR_HW_RXF_OV          		0x00000008 /* RXF overflow interrupt */
+#define ISR_RFD0_UR			0x00000010 /* RFD0 under run */
+#define ISR_RFD1_UR			0x00000020
+#define ISR_RFD2_UR			0x00000040
+#define ISR_RFD3_UR			0x00000080
+#define ISR_TXF_UR			0x00000100
+#define ISR_DMAR_TO_RST			0x00000200
+#define ISR_DMAW_TO_RST			0x00000400
+#define ISR_TX_CREDIT			0x00000800
+#define ISR_GPHY			0x00001000
+/* GPHY low power state interrupt */
+#define ISR_GPHY_LPW           		0x00002000
+#define ISR_TXQ_TO_RST			0x00004000
+#define ISR_TX_PKT			0x00008000
+#define ISR_RX_PKT_0			0x00010000
+#define ISR_RX_PKT_1			0x00020000
+#define ISR_RX_PKT_2			0x00040000
+#define ISR_RX_PKT_3			0x00080000
+#define ISR_MAC_RX			0x00100000
+#define ISR_MAC_TX			0x00200000
+#define ISR_UR_DETECTED			0x00400000
+#define ISR_FERR_DETECTED		0x00800000
+#define ISR_NFERR_DETECTED		0x01000000
+#define ISR_CERR_DETECTED		0x02000000
+#define ISR_PHY_LINKDOWN		0x04000000
+#define ISR_DIS_INT			0x80000000
+
+/* Interrupt Mask Register */
+#define REG_IMR				0x1604
+
+#define IMR_NORMAL_MASK		(\
+		ISR_MANUAL	|\
+		ISR_HW_RXF_OV	|\
+		ISR_RFD0_UR	|\
+		ISR_TXF_UR	|\
+		ISR_DMAR_TO_RST	|\
+		ISR_TXQ_TO_RST  |\
+		ISR_DMAW_TO_RST	|\
+		ISR_GPHY	|\
+		ISR_TX_PKT	|\
+		ISR_RX_PKT_0	|\
+		ISR_GPHY_LPW    |\
+		ISR_PHY_LINKDOWN)
+
+#define ISR_RX_PKT 	(\
+	ISR_RX_PKT_0    |\
+	ISR_RX_PKT_1    |\
+	ISR_RX_PKT_2    |\
+	ISR_RX_PKT_3)
+
+#define ISR_OVER	(\
+	ISR_RFD0_UR 	|\
+	ISR_RFD1_UR	|\
+	ISR_RFD2_UR	|\
+	ISR_RFD3_UR	|\
+	ISR_HW_RXF_OV	|\
+	ISR_TXF_UR)
+
+#define ISR_ERROR	(\
+	ISR_DMAR_TO_RST	|\
+	ISR_TXQ_TO_RST  |\
+	ISR_DMAW_TO_RST	|\
+	ISR_PHY_LINKDOWN)
+
+#define REG_INT_RETRIG_TIMER		0x1608
+#define INT_RETRIG_TIMER_MASK		0xFFFF
+
+#define REG_HDS_CTRL			0x160C
+#define HDS_CTRL_EN			0x0001
+#define HDS_CTRL_BACKFILLSIZE_SHIFT	8
+#define HDS_CTRL_BACKFILLSIZE_MASK	0x0FFF
+#define HDS_CTRL_MAX_HDRSIZE_SHIFT	20
+#define HDS_CTRL_MAC_HDRSIZE_MASK	0x0FFF
+
+#define REG_MAC_RX_STATUS_BIN 		0x1700
+#define REG_MAC_RX_STATUS_END 		0x175c
+#define REG_MAC_TX_STATUS_BIN 		0x1760
+#define REG_MAC_TX_STATUS_END 		0x17c0
+
+/* DEBUG ADDR */
+#define REG_DEBUG_DATA0 		0x1900
+#define REG_DEBUG_DATA1 		0x1904
+
+/* PHY Control Register */
+#define MII_BMCR			0x00
+#define BMCR_SPEED_SELECT_MSB		0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define BMCR_COLL_TEST_ENABLE		0x0080  /* Collision test enable */
+#define BMCR_FULL_DUPLEX		0x0100  /* FDX =1, half duplex =0 */
+#define BMCR_RESTART_AUTO_NEG		0x0200  /* Restart auto negotiation */
+#define BMCR_ISOLATE			0x0400  /* Isolate PHY from MII */
+#define BMCR_POWER_DOWN			0x0800  /* Power down */
+#define BMCR_AUTO_NEG_EN		0x1000  /* Auto Neg Enable */
+#define BMCR_SPEED_SELECT_LSB		0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define BMCR_LOOPBACK			0x4000  /* 0 = normal, 1 = loopback */
+#define BMCR_RESET			0x8000  /* 0 = normal, 1 = PHY reset */
+#define BMCR_SPEED_MASK			0x2040
+#define BMCR_SPEED_1000			0x0040
+#define BMCR_SPEED_100			0x2000
+#define BMCR_SPEED_10			0x0000
+
+/* PHY Status Register */
+#define MII_BMSR			0x01
+#define BMMSR_EXTENDED_CAPS		0x0001  /* Extended register capabilities */
+#define BMSR_JABBER_DETECT		0x0002  /* Jabber Detected */
+#define BMSR_LINK_STATUS		0x0004  /* Link Status 1 = link */
+#define BMSR_AUTONEG_CAPS		0x0008  /* Auto Neg Capable */
+#define BMSR_REMOTE_FAULT		0x0010  /* Remote Fault Detect */
+#define BMSR_AUTONEG_COMPLETE		0x0020  /* Auto Neg Complete */
+#define BMSR_PREAMBLE_SUPPRESS		0x0040  /* Preamble may be suppressed */
+#define BMSR_EXTENDED_STATUS		0x0100  /* Ext. status info in Reg 0x0F */
+#define BMSR_100T2_HD_CAPS		0x0200  /* 100T2 Half Duplex Capable */
+#define BMSR_100T2_FD_CAPS		0x0400  /* 100T2 Full Duplex Capable */
+#define BMSR_10T_HD_CAPS		0x0800  /* 10T   Half Duplex Capable */
+#define BMSR_10T_FD_CAPS		0x1000  /* 10T   Full Duplex Capable */
+#define BMSR_100X_HD_CAPS		0x2000  /* 100X  Half Duplex Capable */
+#define BMMII_SR_100X_FD_CAPS		0x4000  /* 100X  Full Duplex Capable */
+#define BMMII_SR_100T4_CAPS		0x8000  /* 100T4 Capable */
+
+#define MII_PHYSID1			0x02
+#define MII_PHYSID2			0x03
+
+/* Autoneg Advertisement Register */
+#define MII_ADVERTISE			0x04
+#define ADVERTISE_SPEED_MASK		0x01E0
+#define ADVERTISE_DEFAULT_CAP		0x0DE0
+
+/* 1000BASE-T Control Register */
+#define MII_GIGA_CR			0x09
+#define GIGA_CR_1000T_REPEATER_DTE	0x0400  /* 1=Repeater/switch device port 0=DTE device */
+
+#define GIGA_CR_1000T_MS_VALUE		0x0800  /* 1=Configure PHY as Master 0=Configure PHY as Slave */
+#define GIGA_CR_1000T_MS_ENABLE		0x1000  /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */
+#define GIGA_CR_1000T_TEST_MODE_NORMAL	0x0000  /* Normal Operation */
+#define GIGA_CR_1000T_TEST_MODE_1	0x2000  /* Transmit Waveform test */
+#define GIGA_CR_1000T_TEST_MODE_2	0x4000  /* Master Transmit Jitter test */
+#define GIGA_CR_1000T_TEST_MODE_3	0x6000  /* Slave Transmit Jitter test */
+#define GIGA_CR_1000T_TEST_MODE_4	0x8000	/* Transmitter Distortion test */
+#define GIGA_CR_1000T_SPEED_MASK	0x0300
+#define GIGA_CR_1000T_DEFAULT_CAP	0x0300
+
+/* PHY Specific Status Register */
+#define MII_GIGA_PSSR			0x11
+#define GIGA_PSSR_SPD_DPLX_RESOLVED	0x0800  /* 1=Speed & Duplex resolved */
+#define GIGA_PSSR_DPLX			0x2000  /* 1=Duplex 0=Half Duplex */
+#define GIGA_PSSR_SPEED			0xC000  /* Speed, bits 14:15 */
+#define GIGA_PSSR_10MBS			0x0000  /* 00=10Mbs */
+#define GIGA_PSSR_100MBS		0x4000  /* 01=100Mbs */
+#define GIGA_PSSR_1000MBS		0x8000  /* 10=1000Mbs */
+
+/* PHY Interrupt Enable Register */
+#define MII_IER				0x12
+#define IER_LINK_UP			0x0400
+#define IER_LINK_DOWN			0x0800
+
+/* PHY Interrupt Status Register */
+#define MII_ISR				0x13
+#define ISR_LINK_UP			0x0400
+#define ISR_LINK_DOWN			0x0800
+
+/* Cable-Detect-Test Control Register */
+#define MII_CDTC			0x16
+#define CDTC_EN_OFF			0   /* sc */
+#define CDTC_EN_BITS			1
+#define CDTC_PAIR_OFF			8
+#define CDTC_PAIR_BIT			2
+
+/* Cable-Detect-Test Status Register */
+#define MII_CDTS			0x1C
+#define CDTS_STATUS_OFF			8
+#define CDTS_STATUS_BITS		2
+#define CDTS_STATUS_NORMAL		0
+#define CDTS_STATUS_SHORT		1
+#define CDTS_STATUS_OPEN		2
+#define CDTS_STATUS_INVALID		3
+
+#define MII_DBG_ADDR			0x1D
+#define MII_DBG_DATA			0x1E
+
+#define MII_ANA_CTRL_0			0x0
+#define ANA_RESTART_CAL			0x0001
+#define ANA_MANUL_SWICH_ON_SHIFT	0x1
+#define ANA_MANUL_SWICH_ON_MASK		0xF
+#define ANA_MAN_ENABLE			0x0020
+#define ANA_SEL_HSP			0x0040
+#define ANA_EN_HB			0x0080
+#define ANA_EN_HBIAS			0x0100
+#define ANA_OEN_125M			0x0200
+#define ANA_EN_LCKDT			0x0400
+#define ANA_LCKDT_PHY			0x0800
+#define ANA_AFE_MODE			0x1000
+#define ANA_VCO_SLOW			0x2000
+#define ANA_VCO_FAST			0x4000
+#define ANA_SEL_CLK125M_DSP		0x8000
+
+#define MII_ANA_CTRL_4			0x4
+#define ANA_IECHO_ADJ_MASK		0xF
+#define ANA_IECHO_ADJ_3_SHIFT		0
+#define ANA_IECHO_ADJ_2_SHIFT		4
+#define ANA_IECHO_ADJ_1_SHIFT		8
+#define ANA_IECHO_ADJ_0_SHIFT		12
+
+#define MII_ANA_CTRL_5			0x5
+#define ANA_SERDES_CDR_BW_SHIFT		0
+#define ANA_SERDES_CDR_BW_MASK		0x3
+#define ANA_MS_PAD_DBG			0x0004
+#define ANA_SPEEDUP_DBG			0x0008
+#define ANA_SERDES_TH_LOS_SHIFT		4
+#define ANA_SERDES_TH_LOS_MASK		0x3
+#define ANA_SERDES_EN_DEEM		0x0040
+#define ANA_SERDES_TXELECIDLE		0x0080
+#define ANA_SERDES_BEACON		0x0100
+#define ANA_SERDES_HALFTXDR		0x0200
+#define ANA_SERDES_SEL_HSP		0x0400
+#define ANA_SERDES_EN_PLL		0x0800
+#define ANA_SERDES_EN			0x1000
+#define ANA_SERDES_EN_LCKDT		0x2000
+
+#define MII_ANA_CTRL_11			0xB
+#define ANA_PS_HIB_EN			0x8000
+
+#define MII_ANA_CTRL_18			0x12
+#define ANA_TEST_MODE_10BT_01SHIFT	0
+#define ANA_TEST_MODE_10BT_01MASK	0x3
+#define ANA_LOOP_SEL_10BT		0x0004
+#define ANA_RGMII_MODE_SW		0x0008
+#define ANA_EN_LONGECABLE		0x0010
+#define ANA_TEST_MODE_10BT_2		0x0020
+#define ANA_EN_10BT_IDLE		0x0400
+#define ANA_EN_MASK_TB			0x0800
+#define ANA_TRIGGER_SEL_TIMER_SHIFT	12
+#define ANA_TRIGGER_SEL_TIMER_MASK	0x3
+#define ANA_INTERVAL_SEL_TIMER_SHIFT	14
+#define ANA_INTERVAL_SEL_TIMER_MASK	0x3
+
+#define MII_ANA_CTRL_41			0x29
+#define ANA_TOP_PS_EN			0x8000
+
+#define MII_ANA_CTRL_54			0x36
+#define ANA_LONG_CABLE_TH_100_SHIFT	0
+#define ANA_LONG_CABLE_TH_100_MASK	0x3F
+#define ANA_DESERVED			0x0040
+#define ANA_EN_LIT_CH			0x0080
+#define ANA_SHORT_CABLE_TH_100_SHIFT	8
+#define ANA_SHORT_CABLE_TH_100_MASK	0x3F
+#define ANA_BP_BAD_LINK_ACCUM		0x4000
+#define ANA_BP_SMALL_BW			0x8000
+
+#endif /*_ATL1C_HW_H_*/
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
new file mode 100644
index 0000000..deb7b53
--- /dev/null
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -0,0 +1,2797 @@
+/*
+ * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
+ *
+ * Derived from Intel e1000 driver
+ * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; 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.
+ */
+
+#include "atl1c.h"
+
+#define ATL1C_DRV_VERSION "1.0.0.1-NAPI"
+char atl1c_driver_name[] = "atl1c";
+char atl1c_driver_version[] = ATL1C_DRV_VERSION;
+#define PCI_DEVICE_ID_ATTANSIC_L2C      0x1062
+#define PCI_DEVICE_ID_ATTANSIC_L1C      0x1063
+/*
+ * atl1c_pci_tbl - PCI Device ID Table
+ *
+ * Wildcard entries (PCI_ANY_ID) should come last
+ * Last entry must be all 0s
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ *   Class, Class Mask, private data (not used) }
+ */
+static struct pci_device_id atl1c_pci_tbl[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)},
+	{PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)},
+	/* required last entry */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl);
+
+MODULE_AUTHOR("Jie Yang <jie.yang@atheros.com>");
+MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ATL1C_DRV_VERSION);
+
+static int atl1c_stop_mac(struct atl1c_hw *hw);
+static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw);
+static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw);
+static void atl1c_disable_l0s_l1(struct atl1c_hw *hw);
+static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup);
+static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter);
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+		   int *work_done, int work_to_do);
+
+static const u16 atl1c_pay_load_size[] = {
+	128, 256, 512, 1024, 2048, 4096,
+};
+
+static const u16 atl1c_rfd_prod_idx_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+	REG_MB_RFD0_PROD_IDX,
+	REG_MB_RFD1_PROD_IDX,
+	REG_MB_RFD2_PROD_IDX,
+	REG_MB_RFD3_PROD_IDX
+};
+
+static const u16 atl1c_rfd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+	REG_RFD0_HEAD_ADDR_LO,
+	REG_RFD1_HEAD_ADDR_LO,
+	REG_RFD2_HEAD_ADDR_LO,
+	REG_RFD3_HEAD_ADDR_LO
+};
+
+static const u16 atl1c_rrd_addr_lo_regs[AT_MAX_RECEIVE_QUEUE] =
+{
+	REG_RRD0_HEAD_ADDR_LO,
+	REG_RRD1_HEAD_ADDR_LO,
+	REG_RRD2_HEAD_ADDR_LO,
+	REG_RRD3_HEAD_ADDR_LO
+};
+
+static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
+	NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP;
+
+/*
+ * atl1c_init_pcie - init PCIE module
+ */
+static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)
+{
+	u32 data;
+	u32 pci_cmd;
+	struct pci_dev *pdev = hw->adapter->pdev;
+
+	AT_READ_REG(hw, PCI_COMMAND, &pci_cmd);
+	pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+	pci_cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+		PCI_COMMAND_IO);
+	AT_WRITE_REG(hw, PCI_COMMAND, pci_cmd);
+
+	/*
+	 * Clear any PowerSaveing Settings
+	 */
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	/*
+	 * Mask some pcie error bits
+	 */
+	AT_READ_REG(hw, REG_PCIE_UC_SEVERITY, &data);
+	data &= ~PCIE_UC_SERVRITY_DLP;
+	data &= ~PCIE_UC_SERVRITY_FCP;
+	AT_WRITE_REG(hw, REG_PCIE_UC_SEVERITY, data);
+
+	if (flag & ATL1C_PCIE_L0S_L1_DISABLE)
+		atl1c_disable_l0s_l1(hw);
+	if (flag & ATL1C_PCIE_PHY_RESET)
+		AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
+	else
+		AT_WRITE_REG(hw, REG_GPHY_CTRL,
+			GPHY_CTRL_DEFAULT | GPHY_CTRL_EXT_RESET);
+
+	msleep(1);
+}
+
+/*
+ * atl1c_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ */
+static inline void atl1c_irq_enable(struct atl1c_adapter *adapter)
+{
+	if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
+		AT_WRITE_REG(&adapter->hw, REG_ISR, 0x7FFFFFFF);
+		AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
+		AT_WRITE_FLUSH(&adapter->hw);
+	}
+}
+
+/*
+ * atl1c_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1c_irq_disable(struct atl1c_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	AT_WRITE_REG(&adapter->hw, REG_IMR, 0);
+	AT_WRITE_FLUSH(&adapter->hw);
+	synchronize_irq(adapter->pdev->irq);
+}
+
+/*
+ * atl1c_irq_reset - reset interrupt confiure on the NIC
+ * @adapter: board private structure
+ */
+static inline void atl1c_irq_reset(struct atl1c_adapter *adapter)
+{
+	atomic_set(&adapter->irq_sem, 1);
+	atl1c_irq_enable(adapter);
+}
+
+/*
+ * atl1c_phy_config - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ */
+static void atl1c_phy_config(unsigned long data)
+{
+	struct atl1c_adapter *adapter = (struct atl1c_adapter *) data;
+	struct atl1c_hw *hw = &adapter->hw;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	atl1c_restart_autoneg(hw);
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+}
+
+void atl1c_reinit_locked(struct atl1c_adapter *adapter)
+{
+
+	WARN_ON(in_interrupt());
+	atl1c_down(adapter);
+	atl1c_up(adapter);
+	clear_bit(__AT_RESETTING, &adapter->flags);
+}
+
+static void atl1c_reset_task(struct work_struct *work)
+{
+	struct atl1c_adapter *adapter;
+	struct net_device *netdev;
+
+	adapter = container_of(work, struct atl1c_adapter, reset_task);
+	netdev = adapter->netdev;
+
+	netif_device_detach(netdev);
+	atl1c_down(adapter);
+	atl1c_up(adapter);
+	netif_device_attach(netdev);
+}
+
+static void atl1c_check_link_status(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev    *pdev   = adapter->pdev;
+	int err;
+	unsigned long flags;
+	u16 speed, duplex, phy_data;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	/* MII_BMSR must read twise */
+	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+
+	if ((phy_data & BMSR_LSTATUS) == 0) {
+		/* link down */
+		if (netif_carrier_ok(netdev)) {
+			hw->hibernate = true;
+			atl1c_set_aspm(hw, false);
+			if (atl1c_stop_mac(hw) != 0)
+				if (netif_msg_hw(adapter))
+					dev_warn(&pdev->dev,
+						"stop mac failed\n");
+		}
+		netif_carrier_off(netdev);
+	} else {
+		/* Link Up */
+		hw->hibernate = false;
+		spin_lock_irqsave(&adapter->mdio_lock, flags);
+		err = atl1c_get_speed_and_duplex(hw, &speed, &duplex);
+		spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+		if (unlikely(err))
+			return;
+		/* link result is our setting */
+		if (adapter->link_speed != speed ||
+		    adapter->link_duplex != duplex) {
+			adapter->link_speed  = speed;
+			adapter->link_duplex = duplex;
+			atl1c_enable_tx_ctrl(hw);
+			atl1c_enable_rx_ctrl(hw);
+			atl1c_setup_mac_ctrl(adapter);
+			atl1c_set_aspm(hw, true);
+			if (netif_msg_link(adapter))
+				dev_info(&pdev->dev,
+					"%s: %s NIC Link is Up<%d Mbps %s>\n",
+					atl1c_driver_name, netdev->name,
+					adapter->link_speed,
+					adapter->link_duplex == FULL_DUPLEX ?
+					"Full Duplex" : "Half Duplex");
+		}
+		if (!netif_carrier_ok(netdev))
+			netif_carrier_on(netdev);
+	}
+}
+
+/*
+ * atl1c_link_chg_task - deal with link change event Out of interrupt context
+ * @netdev: network interface device structure
+ */
+static void atl1c_link_chg_task(struct work_struct *work)
+{
+	struct atl1c_adapter *adapter;
+
+	adapter = container_of(work, struct atl1c_adapter, link_chg_task);
+	atl1c_check_link_status(adapter);
+}
+
+static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct pci_dev    *pdev   = adapter->pdev;
+	u16 phy_data;
+	u16 link_up;
+
+	spin_lock(&adapter->mdio_lock);
+	atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data);
+	spin_unlock(&adapter->mdio_lock);
+	link_up = phy_data & BMSR_LSTATUS;
+	/* notify upper layer link down ASAP */
+	if (!link_up) {
+		if (netif_carrier_ok(netdev)) {
+			/* old link state: Up */
+			netif_carrier_off(netdev);
+			if (netif_msg_link(adapter))
+				dev_info(&pdev->dev,
+					"%s: %s NIC Link is Down\n",
+					atl1c_driver_name, netdev->name);
+			adapter->link_speed = SPEED_0;
+		}
+	}
+	schedule_work(&adapter->link_chg_task);
+}
+
+static void atl1c_del_timer(struct atl1c_adapter *adapter)
+{
+	del_timer_sync(&adapter->phy_config_timer);
+}
+
+static void atl1c_cancel_work(struct atl1c_adapter *adapter)
+{
+	cancel_work_sync(&adapter->reset_task);
+	cancel_work_sync(&adapter->link_chg_task);
+}
+
+/*
+ * atl1c_tx_timeout - Respond to a Tx Hang
+ * @netdev: network interface device structure
+ */
+static void atl1c_tx_timeout(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	/* Do the reset outside of interrupt context */
+	schedule_work(&adapter->reset_task);
+}
+
+/*
+ * atl1c_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated.  This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ */
+static void atl1c_set_multi(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	struct dev_mc_list *mc_ptr;
+	u32 mac_ctrl_data;
+	u32 hash_value;
+
+	/* Check for Promiscuous and All Multicast modes */
+	AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data);
+
+	if (netdev->flags & IFF_PROMISC) {
+		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+	} else if (netdev->flags & IFF_ALLMULTI) {
+		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+		mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN;
+	} else {
+		mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN);
+	}
+
+	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+	/* clear the old settings from the multicast hash table */
+	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
+	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
+
+	/* comoute mc addresses' hash value ,and put it into hash table */
+	for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+		hash_value = atl1c_hash_mc_addr(hw, mc_ptr->dmi_addr);
+		atl1c_hash_set(hw, hash_value);
+	}
+}
+
+static void atl1c_vlan_rx_register(struct net_device *netdev,
+				   struct vlan_group *grp)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	u32 mac_ctrl_data = 0;
+
+	if (netif_msg_pktdata(adapter))
+		dev_dbg(&pdev->dev, "atl1c_vlan_rx_register\n");
+
+	atl1c_irq_disable(adapter);
+
+	adapter->vlgrp = grp;
+	AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data);
+
+	if (grp) {
+		/* enable VLAN tag insert/strip */
+		mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+	} else {
+		/* disable VLAN tag insert/strip */
+		mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN;
+	}
+
+	AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data);
+	atl1c_irq_enable(adapter);
+}
+
+static void atl1c_restore_vlan(struct atl1c_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	if (netif_msg_pktdata(adapter))
+		dev_dbg(&pdev->dev, "atl1c_restore_vlan !");
+	atl1c_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+}
+/*
+ * atl1c_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct sockaddr *addr = p;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	if (netif_running(netdev))
+		return -EBUSY;
+
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
+
+	atl1c_hw_set_mac_addr(&adapter->hw);
+
+	return 0;
+}
+
+static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter,
+				struct net_device *dev)
+{
+	int mtu = dev->mtu;
+
+	adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ?
+		roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE;
+}
+/*
+ * atl1c_change_mtu - Change the Maximum Transfer Unit
+ * @netdev: network interface device structure
+ * @new_mtu: new value for maximum frame size
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	int old_mtu   = netdev->mtu;
+	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+
+	if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
+			(max_frame > MAX_JUMBO_FRAME_SIZE)) {
+		if (netif_msg_link(adapter))
+			dev_warn(&adapter->pdev->dev, "invalid MTU setting\n");
+		return -EINVAL;
+	}
+	/* set MTU */
+	if (old_mtu != new_mtu && netif_running(netdev)) {
+		while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
+			msleep(1);
+		netdev->mtu = new_mtu;
+		adapter->hw.max_frame_size = new_mtu;
+		atl1c_set_rxbufsize(adapter, netdev);
+		atl1c_down(adapter);
+		atl1c_up(adapter);
+		clear_bit(__AT_RESETTING, &adapter->flags);
+		if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
+			u32 phy_data;
+
+			AT_READ_REG(&adapter->hw, 0x1414, &phy_data);
+			phy_data |= 0x10000000;
+			AT_WRITE_REG(&adapter->hw, 0x1414, phy_data);
+		}
+
+	}
+	return 0;
+}
+
+/*
+ *  caller should hold mdio_lock
+ */
+static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	u16 result;
+
+	atl1c_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result);
+	return result;
+}
+
+static void atl1c_mdio_write(struct net_device *netdev, int phy_id,
+			     int reg_num, int val)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	atl1c_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val);
+}
+
+/*
+ * atl1c_mii_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1c_mii_ioctl(struct net_device *netdev,
+			   struct ifreq *ifr, int cmd)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	struct mii_ioctl_data *data = if_mii(ifr);
+	unsigned long flags;
+	int retval = 0;
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	spin_lock_irqsave(&adapter->mdio_lock, flags);
+	switch (cmd) {
+	case SIOCGMIIPHY:
+		data->phy_id = 0;
+		break;
+
+	case SIOCGMIIREG:
+		if (!capable(CAP_NET_ADMIN)) {
+			retval = -EPERM;
+			goto out;
+		}
+		if (atl1c_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+				    &data->val_out)) {
+			retval = -EIO;
+			goto out;
+		}
+		break;
+
+	case SIOCSMIIREG:
+		if (!capable(CAP_NET_ADMIN)) {
+			retval = -EPERM;
+			goto out;
+		}
+		if (data->reg_num & ~(0x1F)) {
+			retval = -EFAULT;
+			goto out;
+		}
+
+		dev_dbg(&pdev->dev, "<atl1c_mii_ioctl> write %x %x",
+				data->reg_num, data->val_in);
+		if (atl1c_write_phy_reg(&adapter->hw,
+				     data->reg_num, data->val_in)) {
+			retval = -EIO;
+			goto out;
+		}
+		break;
+
+	default:
+		retval = -EOPNOTSUPP;
+		break;
+	}
+out:
+	spin_unlock_irqrestore(&adapter->mdio_lock, flags);
+	return retval;
+}
+
+/*
+ * atl1c_ioctl -
+ * @netdev:
+ * @ifreq:
+ * @cmd:
+ */
+static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		return atl1c_mii_ioctl(netdev, ifr, cmd);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/*
+ * atl1c_alloc_queues - Allocate memory for all rings
+ * @adapter: board private structure to initialize
+ *
+ */
+static int __devinit atl1c_alloc_queues(struct atl1c_adapter *adapter)
+{
+	return 0;
+}
+
+static void atl1c_set_mac_type(struct atl1c_hw *hw)
+{
+	switch (hw->device_id) {
+	case PCI_DEVICE_ID_ATTANSIC_L2C:
+		hw->nic_type = athr_l2c;
+		break;
+
+	case PCI_DEVICE_ID_ATTANSIC_L1C:
+		hw->nic_type = athr_l1c;
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int atl1c_setup_mac_funcs(struct atl1c_hw *hw)
+{
+	u32 phy_status_data;
+	u32 link_ctrl_data;
+
+	atl1c_set_mac_type(hw);
+	AT_READ_REG(hw, REG_PHY_STATUS, &phy_status_data);
+	AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data);
+
+	hw->ctrl_flags = ATL1C_INTR_CLEAR_ON_READ |
+			 ATL1C_INTR_MODRT_ENABLE  |
+			 ATL1C_RX_IPV6_CHKSUM	  |
+			 ATL1C_TXQ_MODE_ENHANCE;
+	if (link_ctrl_data & LINK_CTRL_L0S_EN)
+		hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT;
+	if (link_ctrl_data & LINK_CTRL_L1_EN)
+		hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT;
+
+	if (hw->nic_type == athr_l1c) {
+		hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON;
+		hw->ctrl_flags |= ATL1C_LINK_CAP_1000M;
+	}
+	return 0;
+}
+/*
+ * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter)
+ * @adapter: board private structure to initialize
+ *
+ * atl1c_sw_init initializes the Adapter private data structure.
+ * Fields are initialized based on PCI device information and
+ * OS network device settings (MTU size).
+ */
+static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw   = &adapter->hw;
+	struct pci_dev	*pdev = adapter->pdev;
+
+	adapter->wol = 0;
+	adapter->link_speed = SPEED_0;
+	adapter->link_duplex = FULL_DUPLEX;
+	adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE;
+	adapter->tpd_ring[0].count = 1024;
+	adapter->rfd_ring[0].count = 512;
+
+	hw->vendor_id = pdev->vendor;
+	hw->device_id = pdev->device;
+	hw->subsystem_vendor_id = pdev->subsystem_vendor;
+	hw->subsystem_id = pdev->subsystem_device;
+
+	/* before link up, we assume hibernate is true */
+	hw->hibernate = true;
+	hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
+	if (atl1c_setup_mac_funcs(hw) != 0) {
+		dev_err(&pdev->dev, "set mac function pointers failed\n");
+		return -1;
+	}
+	hw->intr_mask = IMR_NORMAL_MASK;
+	hw->phy_configured = false;
+	hw->preamble_len = 7;
+	hw->max_frame_size = adapter->netdev->mtu;
+	if (adapter->num_rx_queues < 2) {
+		hw->rss_type = atl1c_rss_disable;
+		hw->rss_mode = atl1c_rss_mode_disable;
+	} else {
+		hw->rss_type = atl1c_rss_ipv4;
+		hw->rss_mode = atl1c_rss_mul_que_mul_int;
+		hw->rss_hash_bits = 16;
+	}
+	hw->autoneg_advertised = ADVERTISED_Autoneg;
+	hw->indirect_tab = 0xE4E4E4E4;
+	hw->base_cpu = 0;
+
+	hw->ict = 50000;		/* 100ms */
+	hw->smb_timer = 200000;	  	/* 400ms */
+	hw->cmb_tpd = 4;
+	hw->cmb_tx_timer = 1;		/* 2 us  */
+	hw->rx_imt = 200;
+	hw->tx_imt = 1000;
+
+	hw->tpd_burst = 5;
+	hw->rfd_burst = 8;
+	hw->dma_order = atl1c_dma_ord_out;
+	hw->dmar_block = atl1c_dma_req_1024;
+	hw->dmaw_block = atl1c_dma_req_1024;
+	hw->dmar_dly_cnt = 15;
+	hw->dmaw_dly_cnt = 4;
+
+	if (atl1c_alloc_queues(adapter)) {
+		dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+		return -ENOMEM;
+	}
+	/* TODO */
+	atl1c_set_rxbufsize(adapter, adapter->netdev);
+	atomic_set(&adapter->irq_sem, 1);
+	spin_lock_init(&adapter->mdio_lock);
+	spin_lock_init(&adapter->tx_lock);
+	set_bit(__AT_DOWN, &adapter->flags);
+
+	return 0;
+}
+
+/*
+ * atl1c_clean_tx_ring - Free Tx-skb
+ * @adapter: board private structure
+ */
+static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter,
+				enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+	struct atl1c_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	u16 index, ring_count;
+
+	ring_count = tpd_ring->count;
+	for (index = 0; index < ring_count; index++) {
+		buffer_info = &tpd_ring->buffer_info[index];
+		if (buffer_info->state == ATL1_BUFFER_FREE)
+			continue;
+		if (buffer_info->dma)
+			pci_unmap_single(pdev, buffer_info->dma,
+					buffer_info->length,
+					PCI_DMA_TODEVICE);
+		if (buffer_info->skb)
+			dev_kfree_skb(buffer_info->skb);
+		buffer_info->dma = 0;
+		buffer_info->skb = NULL;
+		buffer_info->state = ATL1_BUFFER_FREE;
+	}
+
+	/* Zero out Tx-buffers */
+	memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) *
+				ring_count);
+	atomic_set(&tpd_ring->next_to_clean, 0);
+	tpd_ring->next_to_use = 0;
+}
+
+/*
+ * atl1c_clean_rx_ring - Free rx-reservation skbs
+ * @adapter: board private structure
+ */
+static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter)
+{
+	struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
+	struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+	struct atl1c_buffer *buffer_info;
+	struct pci_dev *pdev = adapter->pdev;
+	int i, j;
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		for (j = 0; j < rfd_ring[i].count; j++) {
+			buffer_info = &rfd_ring[i].buffer_info[j];
+			if (buffer_info->state == ATL1_BUFFER_FREE)
+				continue;
+			if (buffer_info->dma)
+				pci_unmap_single(pdev, buffer_info->dma,
+						buffer_info->length,
+						PCI_DMA_FROMDEVICE);
+			if (buffer_info->skb)
+				dev_kfree_skb(buffer_info->skb);
+			buffer_info->state = ATL1_BUFFER_FREE;
+			buffer_info->skb = NULL;
+		}
+		/* zero out the descriptor ring */
+		memset(rfd_ring[i].desc, 0, rfd_ring[i].size);
+		rfd_ring[i].next_to_clean = 0;
+		rfd_ring[i].next_to_use = 0;
+		rrd_ring[i].next_to_use = 0;
+		rrd_ring[i].next_to_clean = 0;
+	}
+}
+
+/*
+ * Read / Write Ptr Initialize:
+ */
+static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter)
+{
+	struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
+	struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
+	struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+	struct atl1c_buffer *buffer_info;
+	int i, j;
+
+	for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
+		tpd_ring[i].next_to_use = 0;
+		atomic_set(&tpd_ring[i].next_to_clean, 0);
+		buffer_info = tpd_ring[i].buffer_info;
+		for (j = 0; j < tpd_ring->count; j++)
+			buffer_info[i].state = ATL1_BUFFER_FREE;
+	}
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		rfd_ring[i].next_to_use = 0;
+		rfd_ring[i].next_to_clean = 0;
+		rrd_ring[i].next_to_use = 0;
+		rrd_ring[i].next_to_clean = 0;
+		for (j = 0; j < rfd_ring[i].count; j++) {
+			buffer_info = &rfd_ring[i].buffer_info[j];
+			buffer_info->state = ATL1_BUFFER_FREE;
+		}
+	}
+}
+
+/*
+ * atl1c_free_ring_resources - Free Tx / RX descriptor Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void atl1c_free_ring_resources(struct atl1c_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+
+	pci_free_consistent(pdev, adapter->ring_header.size,
+					adapter->ring_header.desc,
+					adapter->ring_header.dma);
+	adapter->ring_header.desc = NULL;
+
+	/* Note: just free tdp_ring.buffer_info,
+	*  it contain rfd_ring.buffer_info, do not double free */
+	if (adapter->tpd_ring[0].buffer_info) {
+		kfree(adapter->tpd_ring[0].buffer_info);
+		adapter->tpd_ring[0].buffer_info = NULL;
+	}
+}
+
+/*
+ * atl1c_setup_mem_resources - allocate Tx / RX descriptor resources
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ */
+static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
+	struct atl1c_rfd_ring *rfd_ring = adapter->rfd_ring;
+	struct atl1c_rrd_ring *rrd_ring = adapter->rrd_ring;
+	struct atl1c_ring_header *ring_header = &adapter->ring_header;
+	int num_rx_queues = adapter->num_rx_queues;
+	int size;
+	int i;
+	int count = 0;
+	int rx_desc_count = 0;
+	u32 offset = 0;
+
+	rrd_ring[0].count = rfd_ring[0].count;
+	for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++)
+		tpd_ring[i].count = tpd_ring[0].count;
+
+	for (i = 1; i < adapter->num_rx_queues; i++)
+		rfd_ring[i].count = rrd_ring[i].count = rfd_ring[0].count;
+
+	/* 2 tpd queue, one high priority queue,
+	 * another normal priority queue */
+	size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 +
+		rfd_ring->count * num_rx_queues);
+	tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL);
+	if (unlikely(!tpd_ring->buffer_info)) {
+		dev_err(&pdev->dev, "kzalloc failed, size = %d\n",
+			size);
+		goto err_nomem;
+	}
+	for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
+		tpd_ring[i].buffer_info =
+			(struct atl1c_buffer *) (tpd_ring->buffer_info + count);
+		count += tpd_ring[i].count;
+	}
+
+	for (i = 0; i < num_rx_queues; i++) {
+		rfd_ring[i].buffer_info =
+			(struct atl1c_buffer *) (tpd_ring->buffer_info + count);
+		count += rfd_ring[i].count;
+		rx_desc_count += rfd_ring[i].count;
+	}
+	/*
+	 * real ring DMA buffer
+	 * each ring/block may need up to 8 bytes for alignment, hence the
+	 * additional bytes tacked onto the end.
+	 */
+	ring_header->size = size =
+		sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 +
+		sizeof(struct atl1c_rx_free_desc) * rx_desc_count +
+		sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
+		sizeof(struct atl1c_hw_stats) +
+		8 * 4 + 8 * 2 * num_rx_queues;
+
+	ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
+				&ring_header->dma);
+	if (unlikely(!ring_header->desc)) {
+		dev_err(&pdev->dev, "pci_alloc_consistend failed\n");
+		goto err_nomem;
+	}
+	memset(ring_header->desc, 0, ring_header->size);
+	/* init TPD ring */
+
+	tpd_ring[0].dma = roundup(ring_header->dma, 8);
+	offset = tpd_ring[0].dma - ring_header->dma;
+	for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) {
+		tpd_ring[i].dma = ring_header->dma + offset;
+		tpd_ring[i].desc = (u8 *) ring_header->desc + offset;
+		tpd_ring[i].size =
+			sizeof(struct atl1c_tpd_desc) * tpd_ring[i].count;
+		offset += roundup(tpd_ring[i].size, 8);
+	}
+	/* init RFD ring */
+	for (i = 0; i < num_rx_queues; i++) {
+		rfd_ring[i].dma = ring_header->dma + offset;
+		rfd_ring[i].desc = (u8 *) ring_header->desc + offset;
+		rfd_ring[i].size = sizeof(struct atl1c_rx_free_desc) *
+				rfd_ring[i].count;
+		offset += roundup(rfd_ring[i].size, 8);
+	}
+
+	/* init RRD ring */
+	for (i = 0; i < num_rx_queues; i++) {
+		rrd_ring[i].dma = ring_header->dma + offset;
+		rrd_ring[i].desc = (u8 *) ring_header->desc + offset;
+		rrd_ring[i].size = sizeof(struct atl1c_recv_ret_status) *
+				rrd_ring[i].count;
+		offset += roundup(rrd_ring[i].size, 8);
+	}
+
+	adapter->smb.dma = ring_header->dma + offset;
+	adapter->smb.smb = (u8 *)ring_header->desc + offset;
+	return 0;
+
+err_nomem:
+	kfree(tpd_ring->buffer_info);
+	return -ENOMEM;
+}
+
+static void atl1c_configure_des_ring(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	struct atl1c_rfd_ring *rfd_ring = (struct atl1c_rfd_ring *)
+				adapter->rfd_ring;
+	struct atl1c_rrd_ring *rrd_ring = (struct atl1c_rrd_ring *)
+				adapter->rrd_ring;
+	struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
+				adapter->tpd_ring;
+	struct atl1c_cmb *cmb = (struct atl1c_cmb *) &adapter->cmb;
+	struct atl1c_smb *smb = (struct atl1c_smb *) &adapter->smb;
+	int i;
+
+	/* TPD */
+	AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI,
+			(u32)((tpd_ring[atl1c_trans_normal].dma &
+				AT_DMA_HI_ADDR_MASK) >> 32));
+	/* just enable normal priority TX queue */
+	AT_WRITE_REG(hw, REG_NTPD_HEAD_ADDR_LO,
+			(u32)(tpd_ring[atl1c_trans_normal].dma &
+				AT_DMA_LO_ADDR_MASK));
+	AT_WRITE_REG(hw, REG_HTPD_HEAD_ADDR_LO,
+			(u32)(tpd_ring[atl1c_trans_high].dma &
+				AT_DMA_LO_ADDR_MASK));
+	AT_WRITE_REG(hw, REG_TPD_RING_SIZE,
+			(u32)(tpd_ring[0].count & TPD_RING_SIZE_MASK));
+
+
+	/* RFD */
+	AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI,
+			(u32)((rfd_ring[0].dma & AT_DMA_HI_ADDR_MASK) >> 32));
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		AT_WRITE_REG(hw, atl1c_rfd_addr_lo_regs[i],
+			(u32)(rfd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+
+	AT_WRITE_REG(hw, REG_RFD_RING_SIZE,
+			rfd_ring[0].count & RFD_RING_SIZE_MASK);
+	AT_WRITE_REG(hw, REG_RX_BUF_SIZE,
+			adapter->rx_buffer_len & RX_BUF_SIZE_MASK);
+
+	/* RRD */
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		AT_WRITE_REG(hw, atl1c_rrd_addr_lo_regs[i],
+			(u32)(rrd_ring[i].dma & AT_DMA_LO_ADDR_MASK));
+	AT_WRITE_REG(hw, REG_RRD_RING_SIZE,
+			(rrd_ring[0].count & RRD_RING_SIZE_MASK));
+
+	/* CMB */
+	AT_WRITE_REG(hw, REG_CMB_BASE_ADDR_LO, cmb->dma & AT_DMA_LO_ADDR_MASK);
+
+	/* SMB */
+	AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_HI,
+			(u32)((smb->dma & AT_DMA_HI_ADDR_MASK) >> 32));
+	AT_WRITE_REG(hw, REG_SMB_BASE_ADDR_LO,
+			(u32)(smb->dma & AT_DMA_LO_ADDR_MASK));
+	/* Load all of base address above */
+	AT_WRITE_REG(hw, REG_LOAD_PTR, 1);
+}
+
+static void atl1c_configure_tx(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 dev_ctrl_data;
+	u32 max_pay_load;
+	u16 tx_offload_thresh;
+	u32 txq_ctrl_data;
+	u32 extra_size = 0;     /* Jumbo frame threshold in QWORD unit */
+
+	extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+	tx_offload_thresh = MAX_TX_OFFLOAD_THRESH;
+	AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH,
+		(tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK);
+	AT_READ_REG(hw, REG_DEVICE_CTRL, &dev_ctrl_data);
+	max_pay_load  = (dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT) &
+			DEVICE_CTRL_MAX_PAYLOAD_MASK;
+	hw->dmaw_block = min(max_pay_load, hw->dmaw_block);
+	max_pay_load  = (dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT) &
+			DEVICE_CTRL_MAX_RREQ_SZ_MASK;
+	hw->dmar_block = min(max_pay_load, hw->dmar_block);
+
+	txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) <<
+			TXQ_NUM_TPD_BURST_SHIFT;
+	if (hw->ctrl_flags & ATL1C_TXQ_MODE_ENHANCE)
+		txq_ctrl_data |= TXQ_CTRL_ENH_MODE;
+	txq_ctrl_data |= (atl1c_pay_load_size[hw->dmar_block] &
+			TXQ_TXF_BURST_NUM_MASK) << TXQ_TXF_BURST_NUM_SHIFT;
+
+	AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data);
+}
+
+static void atl1c_configure_rx(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 rxq_ctrl_data;
+
+	rxq_ctrl_data = (hw->rfd_burst & RXQ_RFD_BURST_NUM_MASK) <<
+			RXQ_RFD_BURST_NUM_SHIFT;
+
+	if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM)
+		rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN;
+	if (hw->rss_type == atl1c_rss_ipv4)
+		rxq_ctrl_data |= RSS_HASH_IPV4;
+	if (hw->rss_type == atl1c_rss_ipv4_tcp)
+		rxq_ctrl_data |= RSS_HASH_IPV4_TCP;
+	if (hw->rss_type == atl1c_rss_ipv6)
+		rxq_ctrl_data |= RSS_HASH_IPV6;
+	if (hw->rss_type == atl1c_rss_ipv6_tcp)
+		rxq_ctrl_data |= RSS_HASH_IPV6_TCP;
+	if (hw->rss_type != atl1c_rss_disable)
+		rxq_ctrl_data |= RRS_HASH_CTRL_EN;
+
+	rxq_ctrl_data |= (hw->rss_mode & RSS_MODE_MASK) <<
+			RSS_MODE_SHIFT;
+	rxq_ctrl_data |= (hw->rss_hash_bits & RSS_HASH_BITS_MASK) <<
+			RSS_HASH_BITS_SHIFT;
+	if (hw->ctrl_flags & ATL1C_ASPM_CTRL_MON)
+		rxq_ctrl_data |= (ASPM_THRUPUT_LIMIT_100M &
+			ASPM_THRUPUT_LIMIT_MASK) << ASPM_THRUPUT_LIMIT_SHIFT;
+
+	AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data);
+}
+
+static void atl1c_configure_rss(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+
+	AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab);
+	AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu);
+}
+
+static void atl1c_configure_dma(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 dma_ctrl_data;
+
+	dma_ctrl_data = DMA_CTRL_DMAR_REQ_PRI;
+	if (hw->ctrl_flags & ATL1C_CMB_ENABLE)
+		dma_ctrl_data |= DMA_CTRL_CMB_EN;
+	if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
+		dma_ctrl_data |= DMA_CTRL_SMB_EN;
+	else
+		dma_ctrl_data |= MAC_CTRL_SMB_DIS;
+
+	switch (hw->dma_order) {
+	case atl1c_dma_ord_in:
+		dma_ctrl_data |= DMA_CTRL_DMAR_IN_ORDER;
+		break;
+	case atl1c_dma_ord_enh:
+		dma_ctrl_data |= DMA_CTRL_DMAR_ENH_ORDER;
+		break;
+	case atl1c_dma_ord_out:
+		dma_ctrl_data |= DMA_CTRL_DMAR_OUT_ORDER;
+		break;
+	default:
+		break;
+	}
+
+	dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAR_BURST_LEN_SHIFT;
+	dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK)
+		<< DMA_CTRL_DMAW_BURST_LEN_SHIFT;
+	dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK)
+		<< DMA_CTRL_DMAR_DLY_CNT_SHIFT;
+	dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK)
+		<< DMA_CTRL_DMAW_DLY_CNT_SHIFT;
+
+	AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data);
+}
+
+/*
+ * Stop the mac, transmit and receive units
+ * hw - Struct containing variables accessed by shared code
+ * return : 0  or  idle status (if error)
+ */
+static int atl1c_stop_mac(struct atl1c_hw *hw)
+{
+	u32 data;
+	int timeout;
+
+	AT_READ_REG(hw, REG_RXQ_CTRL, &data);
+	data &= ~(RXQ1_CTRL_EN | RXQ2_CTRL_EN |
+		  RXQ3_CTRL_EN | RXQ_CTRL_EN);
+	AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
+
+	AT_READ_REG(hw, REG_TXQ_CTRL, &data);
+	data &= ~TXQ_CTRL_EN;
+	AT_WRITE_REG(hw, REG_TWSI_CTRL, data);
+
+	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+		AT_READ_REG(hw, REG_IDLE_STATUS, &data);
+		if ((data & (IDLE_STATUS_RXQ_NO_IDLE |
+			IDLE_STATUS_TXQ_NO_IDLE)) == 0)
+			break;
+		msleep(1);
+	}
+
+	AT_READ_REG(hw, REG_MAC_CTRL, &data);
+	data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN);
+	AT_WRITE_REG(hw, REG_MAC_CTRL, data);
+
+	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+		AT_READ_REG(hw, REG_IDLE_STATUS, &data);
+		if ((data & IDLE_STATUS_MASK) == 0)
+			return 0;
+		msleep(1);
+	}
+	return data;
+}
+
+static void atl1c_enable_rx_ctrl(struct atl1c_hw *hw)
+{
+	u32 data;
+
+	AT_READ_REG(hw, REG_RXQ_CTRL, &data);
+	switch (hw->adapter->num_rx_queues) {
+	case 4:
+		data |= (RXQ3_CTRL_EN | RXQ2_CTRL_EN | RXQ1_CTRL_EN);
+		break;
+	case 3:
+		data |= (RXQ2_CTRL_EN | RXQ1_CTRL_EN);
+		break;
+	case 2:
+		data |= RXQ1_CTRL_EN;
+		break;
+	default:
+		break;
+	}
+	data |= RXQ_CTRL_EN;
+	AT_WRITE_REG(hw, REG_RXQ_CTRL, data);
+}
+
+static void atl1c_enable_tx_ctrl(struct atl1c_hw *hw)
+{
+	u32 data;
+
+	AT_READ_REG(hw, REG_TXQ_CTRL, &data);
+	data |= TXQ_CTRL_EN;
+	AT_WRITE_REG(hw, REG_TXQ_CTRL, data);
+}
+
+/*
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ * hw - Struct containing variables accessed by shared code
+ * return : 0  or  idle status (if error)
+ */
+static int atl1c_reset_mac(struct atl1c_hw *hw)
+{
+	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
+	struct pci_dev *pdev = adapter->pdev;
+	u32 idle_status_data = 0;
+	int timeout = 0;
+	int ret;
+
+	AT_WRITE_REG(hw, REG_IMR, 0);
+	AT_WRITE_REG(hw, REG_ISR, ISR_DIS_INT);
+
+	ret = atl1c_stop_mac(hw);
+	if (ret)
+		return ret;
+	/*
+	 * Issue Soft Reset to the MAC.  This will reset the chip's
+	 * transmit, receive, DMA.  It will not effect
+	 * the current PCI configuration.  The global reset bit is self-
+	 * clearing, and should clear within a microsecond.
+	 */
+	AT_WRITE_REGW(hw, REG_MASTER_CTRL, MASTER_CTRL_SOFT_RST);
+	AT_WRITE_FLUSH(hw);
+	msleep(10);
+	/* Wait at least 10ms for All module to be Idle */
+	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
+		AT_READ_REG(hw, REG_IDLE_STATUS, &idle_status_data);
+		if ((idle_status_data & IDLE_STATUS_MASK) == 0)
+			break;
+		msleep(1);
+	}
+	if (timeout >= AT_HW_MAX_IDLE_DELAY) {
+		dev_err(&pdev->dev,
+			"MAC state machine cann't be idle since"
+			" disabled for 10ms second\n");
+		return -1;
+	}
+	return 0;
+}
+
+static void atl1c_disable_l0s_l1(struct atl1c_hw *hw)
+{
+	u32 pm_ctrl_data;
+
+	AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
+	pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
+			PM_CTRL_L1_ENTRY_TIMER_SHIFT);
+	pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
+	pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+	pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+	pm_ctrl_data &= ~PM_CTRL_MAC_ASPM_CHK;
+	pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1;
+
+	pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN;
+	pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
+	pm_ctrl_data |=	PM_CTRL_SERDES_L1_EN;
+	AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
+}
+
+/*
+ * Set ASPM state.
+ * Enable/disable L0s/L1 depend on link state.
+ */
+static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup)
+{
+	u32 pm_ctrl_data;
+
+	AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data);
+
+	pm_ctrl_data &= PM_CTRL_SERDES_PD_EX_L1;
+	pm_ctrl_data |= ~PM_CTRL_SERDES_BUDS_RX_L1_EN;
+	pm_ctrl_data |= ~PM_CTRL_SERDES_L1_EN;
+	pm_ctrl_data &=  ~(PM_CTRL_L1_ENTRY_TIMER_MASK <<
+			PM_CTRL_L1_ENTRY_TIMER_SHIFT);
+
+	pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK;
+
+	if (linkup) {
+		pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN;
+		pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1;
+
+		if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) {
+			pm_ctrl_data |= AT_ASPM_L1_TIMER <<
+				PM_CTRL_L1_ENTRY_TIMER_SHIFT;
+			pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
+		} else
+			pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+
+		if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT)
+			pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN;
+		else
+			pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+
+	} else {
+		pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN;
+		pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN;
+
+		pm_ctrl_data |= PM_CTRL_CLK_SWH_L1;
+
+		if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT)
+			pm_ctrl_data |= PM_CTRL_ASPM_L1_EN;
+		else
+			pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN;
+	}
+
+	AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data);
+}
+
+static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	struct net_device *netdev = adapter->netdev;
+	u32 mac_ctrl_data;
+
+	mac_ctrl_data = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN;
+	mac_ctrl_data |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW);
+
+	if (adapter->link_duplex == FULL_DUPLEX) {
+		hw->mac_duplex = true;
+		mac_ctrl_data |= MAC_CTRL_DUPLX;
+	}
+
+	if (adapter->link_speed == SPEED_1000)
+		hw->mac_speed = atl1c_mac_speed_1000;
+	else
+		hw->mac_speed = atl1c_mac_speed_10_100;
+
+	mac_ctrl_data |= (hw->mac_speed & MAC_CTRL_SPEED_MASK) <<
+			MAC_CTRL_SPEED_SHIFT;
+
+	mac_ctrl_data |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD);
+	mac_ctrl_data |= ((hw->preamble_len & MAC_CTRL_PRMLEN_MASK) <<
+			MAC_CTRL_PRMLEN_SHIFT);
+
+	if (adapter->vlgrp)
+		mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+
+	mac_ctrl_data |= MAC_CTRL_BC_EN;
+	if (netdev->flags & IFF_PROMISC)
+		mac_ctrl_data |= MAC_CTRL_PROMIS_EN;
+	if (netdev->flags & IFF_ALLMULTI)
+		mac_ctrl_data |= MAC_CTRL_MC_ALL_EN;
+
+	mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN;
+	AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+}
+
+/*
+ * atl1c_configure - Configure Transmit&Receive Unit after Reset
+ * @adapter: board private structure
+ *
+ * Configure the Tx /Rx unit of the MAC after a reset.
+ */
+static int atl1c_configure(struct atl1c_adapter *adapter)
+{
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 master_ctrl_data = 0;
+	u32 intr_modrt_data;
+
+	/* clear interrupt status */
+	AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF);
+	/*  Clear any WOL status */
+	AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+	/* set Interrupt Clear Timer
+	 * HW will enable self to assert interrupt event to system after
+	 * waiting x-time for software to notify it accept interrupt.
+	 */
+	AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER,
+		hw->ict & INT_RETRIG_TIMER_MASK);
+
+	atl1c_configure_des_ring(adapter);
+
+	if (hw->ctrl_flags & ATL1C_INTR_MODRT_ENABLE) {
+		intr_modrt_data = (hw->tx_imt & IRQ_MODRT_TIMER_MASK) <<
+					IRQ_MODRT_TX_TIMER_SHIFT;
+		intr_modrt_data |= (hw->rx_imt & IRQ_MODRT_TIMER_MASK) <<
+					IRQ_MODRT_RX_TIMER_SHIFT;
+		AT_WRITE_REG(hw, REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data);
+		master_ctrl_data |=
+			MASTER_CTRL_TX_ITIMER_EN | MASTER_CTRL_RX_ITIMER_EN;
+	}
+
+	if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ)
+		master_ctrl_data |= MASTER_CTRL_INT_RDCLR;
+
+	AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
+
+	if (hw->ctrl_flags & ATL1C_CMB_ENABLE) {
+		AT_WRITE_REG(hw, REG_CMB_TPD_THRESH,
+			hw->cmb_tpd & CMB_TPD_THRESH_MASK);
+		AT_WRITE_REG(hw, REG_CMB_TX_TIMER,
+			hw->cmb_tx_timer & CMB_TX_TIMER_MASK);
+	}
+
+	if (hw->ctrl_flags & ATL1C_SMB_ENABLE)
+		AT_WRITE_REG(hw, REG_SMB_STAT_TIMER,
+			hw->smb_timer & SMB_STAT_TIMER_MASK);
+	/* set MTU */
+	AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN +
+			VLAN_HLEN + ETH_FCS_LEN);
+	/* HDS, disable */
+	AT_WRITE_REG(hw, REG_HDS_CTRL, 0);
+
+	atl1c_configure_tx(adapter);
+	atl1c_configure_rx(adapter);
+	atl1c_configure_rss(adapter);
+	atl1c_configure_dma(adapter);
+
+	return 0;
+}
+
+static void atl1c_update_hw_stats(struct atl1c_adapter *adapter)
+{
+	u16 hw_reg_addr = 0;
+	unsigned long *stats_item = NULL;
+	u32 data;
+
+	/* update rx status */
+	hw_reg_addr = REG_MAC_RX_STATUS_BIN;
+	stats_item  = &adapter->hw_stats.rx_ok;
+	while (hw_reg_addr <= REG_MAC_RX_STATUS_END) {
+		AT_READ_REG(&adapter->hw, hw_reg_addr, &data);
+		*stats_item += data;
+		stats_item++;
+		hw_reg_addr += 4;
+	}
+/* update tx status */
+	hw_reg_addr = REG_MAC_TX_STATUS_BIN;
+	stats_item  = &adapter->hw_stats.tx_ok;
+	while (hw_reg_addr <= REG_MAC_TX_STATUS_END) {
+		AT_READ_REG(&adapter->hw, hw_reg_addr, &data);
+		*stats_item += data;
+		stats_item++;
+		hw_reg_addr += 4;
+	}
+}
+
+/*
+ * atl1c_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ *
+ * Returns the address of the device statistics structure.
+ * The statistics are actually updated from the timer callback.
+ */
+static struct net_device_stats *atl1c_get_stats(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw_stats  *hw_stats = &adapter->hw_stats;
+	struct net_device_stats *net_stats = &adapter->net_stats;
+
+	atl1c_update_hw_stats(adapter);
+	net_stats->rx_packets = hw_stats->rx_ok;
+	net_stats->tx_packets = hw_stats->tx_ok;
+	net_stats->rx_bytes   = hw_stats->rx_byte_cnt;
+	net_stats->tx_bytes   = hw_stats->tx_byte_cnt;
+	net_stats->multicast  = hw_stats->rx_mcast;
+	net_stats->collisions = hw_stats->tx_1_col +
+				hw_stats->tx_2_col * 2 +
+				hw_stats->tx_late_col + hw_stats->tx_abort_col;
+	net_stats->rx_errors  = hw_stats->rx_frag + hw_stats->rx_fcs_err +
+				hw_stats->rx_len_err + hw_stats->rx_sz_ov +
+				hw_stats->rx_rrd_ov + hw_stats->rx_align_err;
+	net_stats->rx_fifo_errors   = hw_stats->rx_rxf_ov;
+	net_stats->rx_length_errors = hw_stats->rx_len_err;
+	net_stats->rx_crc_errors    = hw_stats->rx_fcs_err;
+	net_stats->rx_frame_errors  = hw_stats->rx_align_err;
+	net_stats->rx_over_errors   = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+	net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov;
+
+	net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col +
+				hw_stats->tx_underrun + hw_stats->tx_trunc;
+	net_stats->tx_fifo_errors    = hw_stats->tx_underrun;
+	net_stats->tx_aborted_errors = hw_stats->tx_abort_col;
+	net_stats->tx_window_errors  = hw_stats->tx_late_col;
+
+	return &adapter->net_stats;
+}
+
+static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter)
+{
+	u16 phy_data;
+
+	spin_lock(&adapter->mdio_lock);
+	atl1c_read_phy_reg(&adapter->hw, MII_ISR, &phy_data);
+	spin_unlock(&adapter->mdio_lock);
+}
+
+static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter,
+				enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *)
+				&adapter->tpd_ring[type];
+	struct atl1c_buffer *buffer_info;
+	u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+	u16 hw_next_to_clean;
+	u16 shift;
+	u32 data;
+
+	if (type == atl1c_trans_high)
+		shift = MB_HTPD_CONS_IDX_SHIFT;
+	else
+		shift = MB_NTPD_CONS_IDX_SHIFT;
+
+	AT_READ_REG(&adapter->hw, REG_MB_PRIO_CONS_IDX, &data);
+	hw_next_to_clean = (data >> shift) & MB_PRIO_PROD_IDX_MASK;
+
+	while (next_to_clean != hw_next_to_clean) {
+		buffer_info = &tpd_ring->buffer_info[next_to_clean];
+		if (buffer_info->state == ATL1_BUFFER_BUSY) {
+			pci_unmap_page(adapter->pdev, buffer_info->dma,
+					buffer_info->length, PCI_DMA_TODEVICE);
+			buffer_info->dma = 0;
+			if (buffer_info->skb) {
+				dev_kfree_skb_irq(buffer_info->skb);
+				buffer_info->skb = NULL;
+			}
+			buffer_info->state = ATL1_BUFFER_FREE;
+		}
+		if (++next_to_clean == tpd_ring->count)
+			next_to_clean = 0;
+		atomic_set(&tpd_ring->next_to_clean, next_to_clean);
+	}
+
+	if (netif_queue_stopped(adapter->netdev) &&
+			netif_carrier_ok(adapter->netdev)) {
+		netif_wake_queue(adapter->netdev);
+	}
+
+	return true;
+}
+
+/*
+ * atl1c_intr - Interrupt Handler
+ * @irq: interrupt number
+ * @data: pointer to a network interface device structure
+ * @pt_regs: CPU registers structure
+ */
+static irqreturn_t atl1c_intr(int irq, void *data)
+{
+	struct net_device *netdev  = data;
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1c_hw *hw = &adapter->hw;
+	int max_ints = AT_MAX_INT_WORK;
+	int handled = IRQ_NONE;
+	u32 status;
+	u32 reg_data;
+
+	do {
+		AT_READ_REG(hw, REG_ISR, &reg_data);
+		status = reg_data & hw->intr_mask;
+
+		if (status == 0 || (status & ISR_DIS_INT) != 0) {
+			if (max_ints != AT_MAX_INT_WORK)
+				handled = IRQ_HANDLED;
+			break;
+		}
+		/* link event */
+		if (status & ISR_GPHY)
+			atl1c_clear_phy_int(adapter);
+		/* Ack ISR */
+		AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT);
+		if (status & ISR_RX_PKT) {
+			if (likely(napi_schedule_prep(&adapter->napi))) {
+				hw->intr_mask &= ~ISR_RX_PKT;
+				AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
+				__napi_schedule(&adapter->napi);
+			}
+		}
+		if (status & ISR_TX_PKT)
+			atl1c_clean_tx_irq(adapter, atl1c_trans_normal);
+
+		handled = IRQ_HANDLED;
+		/* check if PCIE PHY Link down */
+		if (status & ISR_ERROR) {
+			if (netif_msg_hw(adapter))
+				dev_err(&pdev->dev,
+					"atl1c hardware error (status = 0x%x)\n",
+					status & ISR_ERROR);
+			/* reset MAC */
+			hw->intr_mask &= ~ISR_ERROR;
+			AT_WRITE_REG(hw, REG_IMR, hw->intr_mask);
+			schedule_work(&adapter->reset_task);
+			break;
+		}
+
+		if (status & ISR_OVER)
+			if (netif_msg_intr(adapter))
+				dev_warn(&pdev->dev,
+					"TX/RX over flow (status = 0x%x)\n",
+					status & ISR_OVER);
+
+		/* link event */
+		if (status & (ISR_GPHY | ISR_MANUAL)) {
+			adapter->net_stats.tx_carrier_errors++;
+			atl1c_link_chg_event(adapter);
+			break;
+		}
+
+	} while (--max_ints > 0);
+	/* re-enable Interrupt*/
+	AT_WRITE_REG(&adapter->hw, REG_ISR, 0);
+	return handled;
+}
+
+static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter,
+		  struct sk_buff *skb, struct atl1c_recv_ret_status *prrs)
+{
+	/*
+	 * The pid field in RRS in not correct sometimes, so we
+	 * cannot figure out if the packet is fragmented or not,
+	 * so we tell the KERNEL CHECKSUM_NONE
+	 */
+	skb->ip_summed = CHECKSUM_NONE;
+}
+
+static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter, const int ringid)
+{
+	struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[ringid];
+	struct pci_dev *pdev = adapter->pdev;
+	struct atl1c_buffer *buffer_info, *next_info;
+	struct sk_buff *skb;
+	void *vir_addr = NULL;
+	u16 num_alloc = 0;
+	u16 rfd_next_to_use, next_next;
+	struct atl1c_rx_free_desc *rfd_desc;
+
+	next_next = rfd_next_to_use = rfd_ring->next_to_use;
+	if (++next_next == rfd_ring->count)
+		next_next = 0;
+	buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+	next_info = &rfd_ring->buffer_info[next_next];
+
+	while (next_info->state == ATL1_BUFFER_FREE) {
+		rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use);
+
+		skb = dev_alloc_skb(adapter->rx_buffer_len);
+		if (unlikely(!skb)) {
+			if (netif_msg_rx_err(adapter))
+				dev_warn(&pdev->dev, "alloc rx buffer failed\n");
+			break;
+		}
+
+		/*
+		 * Make buffer alignment 2 beyond a 16 byte boundary
+		 * this will result in a 16 byte aligned IP header after
+		 * the 14 byte MAC header is removed
+		 */
+		vir_addr = skb->data;
+		buffer_info->state = ATL1_BUFFER_BUSY;
+		buffer_info->skb = skb;
+		buffer_info->length = adapter->rx_buffer_len;
+		buffer_info->dma = pci_map_single(pdev, vir_addr,
+						buffer_info->length,
+						PCI_DMA_FROMDEVICE);
+		rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
+		rfd_next_to_use = next_next;
+		if (++next_next == rfd_ring->count)
+			next_next = 0;
+		buffer_info = &rfd_ring->buffer_info[rfd_next_to_use];
+		next_info = &rfd_ring->buffer_info[next_next];
+		num_alloc++;
+	}
+
+	if (num_alloc) {
+		/* TODO: update mailbox here */
+		wmb();
+		rfd_ring->next_to_use = rfd_next_to_use;
+		AT_WRITE_REG(&adapter->hw, atl1c_rfd_prod_idx_regs[ringid],
+			rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK);
+	}
+
+	return num_alloc;
+}
+
+static void atl1c_clean_rrd(struct atl1c_rrd_ring *rrd_ring,
+			struct	atl1c_recv_ret_status *rrs, u16 num)
+{
+	u16 i;
+	/* the relationship between rrd and rfd is one map one */
+	for (i = 0; i < num; i++, rrs = ATL1C_RRD_DESC(rrd_ring,
+					rrd_ring->next_to_clean)) {
+		rrs->word3 &= ~RRS_RXD_UPDATED;
+		if (++rrd_ring->next_to_clean == rrd_ring->count)
+			rrd_ring->next_to_clean = 0;
+	}
+}
+
+static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring,
+	struct atl1c_recv_ret_status *rrs, u16 num)
+{
+	u16 i;
+	u16 rfd_index;
+	struct atl1c_buffer *buffer_info = rfd_ring->buffer_info;
+
+	rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) &
+			RRS_RX_RFD_INDEX_MASK;
+	for (i = 0; i < num; i++) {
+		buffer_info[rfd_index].skb = NULL;
+		buffer_info[rfd_index].state = ATL1_BUFFER_FREE;
+		if (++rfd_index == rfd_ring->count)
+			rfd_index = 0;
+	}
+	rfd_ring->next_to_clean = rfd_index;
+}
+
+static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
+		   int *work_done, int work_to_do)
+{
+	u16 rfd_num, rfd_index;
+	u16 count = 0;
+	u16 length;
+	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *netdev  = adapter->netdev;
+	struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring[que];
+	struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring[que];
+	struct sk_buff *skb;
+	struct atl1c_recv_ret_status *rrs;
+	struct atl1c_buffer *buffer_info;
+
+	while (1) {
+		if (*work_done >= work_to_do)
+			break;
+		rrs = ATL1C_RRD_DESC(rrd_ring, rrd_ring->next_to_clean);
+		if (likely(RRS_RXD_IS_VALID(rrs->word3))) {
+			rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) &
+				RRS_RX_RFD_CNT_MASK;
+			if (unlikely(rfd_num) != 1)
+				/* TODO support mul rfd*/
+				if (netif_msg_rx_err(adapter))
+					dev_warn(&pdev->dev,
+						"Multi rfd not support yet!\n");
+			goto rrs_checked;
+		} else {
+			break;
+		}
+rrs_checked:
+		atl1c_clean_rrd(rrd_ring, rrs, rfd_num);
+		if (rrs->word3 & (RRS_RX_ERR_SUM | RRS_802_3_LEN_ERR)) {
+			atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
+				if (netif_msg_rx_err(adapter))
+					dev_warn(&pdev->dev,
+						"wrong packet! rrs word3 is %x\n",
+						rrs->word3);
+			continue;
+		}
+
+		length = le16_to_cpu((rrs->word3 >> RRS_PKT_SIZE_SHIFT) &
+				RRS_PKT_SIZE_MASK);
+		/* Good Receive */
+		if (likely(rfd_num == 1)) {
+			rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) &
+					RRS_RX_RFD_INDEX_MASK;
+			buffer_info = &rfd_ring->buffer_info[rfd_index];
+			pci_unmap_single(pdev, buffer_info->dma,
+				buffer_info->length, PCI_DMA_FROMDEVICE);
+			skb = buffer_info->skb;
+		} else {
+			/* TODO */
+			if (netif_msg_rx_err(adapter))
+				dev_warn(&pdev->dev,
+					"Multi rfd not support yet!\n");
+			break;
+		}
+		atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
+		skb_put(skb, length - ETH_FCS_LEN);
+		skb->protocol = eth_type_trans(skb, netdev);
+		skb->dev = netdev;
+		atl1c_rx_checksum(adapter, skb, rrs);
+		if (unlikely(adapter->vlgrp) && rrs->word3 & RRS_VLAN_INS) {
+			u16 vlan;
+
+			AT_TAG_TO_VLAN(rrs->vlan_tag, vlan);
+			vlan = le16_to_cpu(vlan);
+			vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vlan);
+		} else
+			netif_receive_skb(skb);
+
+		netdev->last_rx = jiffies;
+		(*work_done)++;
+		count++;
+	}
+	if (count)
+		atl1c_alloc_rx_buffer(adapter, que);
+}
+
+/*
+ * atl1c_clean - NAPI Rx polling callback
+ * @adapter: board private structure
+ */
+static int atl1c_clean(struct napi_struct *napi, int budget)
+{
+	struct atl1c_adapter *adapter =
+			container_of(napi, struct atl1c_adapter, napi);
+	int work_done = 0;
+
+	/* Keep link state information with original netdev */
+	if (!netif_carrier_ok(adapter->netdev))
+		goto quit_polling;
+	/* just enable one RXQ */
+	atl1c_clean_rx_irq(adapter, 0, &work_done, budget);
+
+	if (work_done < budget) {
+quit_polling:
+		napi_complete(napi);
+		adapter->hw.intr_mask |= ISR_RX_PKT;
+		AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask);
+	}
+	return work_done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void atl1c_netpoll(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	disable_irq(adapter->pdev->irq);
+	atl1c_intr(adapter->pdev->irq, netdev);
+	enable_irq(adapter->pdev->irq);
+}
+#endif
+
+static inline u16 atl1c_tpd_avail(struct atl1c_adapter *adapter, enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+	u16 next_to_use = 0;
+	u16 next_to_clean = 0;
+
+	next_to_clean = atomic_read(&tpd_ring->next_to_clean);
+	next_to_use   = tpd_ring->next_to_use;
+
+	return (u16)(next_to_clean > next_to_use) ?
+		(next_to_clean - next_to_use - 1) :
+		(tpd_ring->count + next_to_clean - next_to_use - 1);
+}
+
+/*
+ * get next usable tpd
+ * Note: should call atl1c_tdp_avail to make sure
+ * there is enough tpd to use
+ */
+static struct atl1c_tpd_desc *atl1c_get_tpd(struct atl1c_adapter *adapter,
+	enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+	struct atl1c_tpd_desc *tpd_desc;
+	u16 next_to_use = 0;
+
+	next_to_use = tpd_ring->next_to_use;
+	if (++tpd_ring->next_to_use == tpd_ring->count)
+		tpd_ring->next_to_use = 0;
+	tpd_desc = ATL1C_TPD_DESC(tpd_ring, next_to_use);
+	memset(tpd_desc, 0, sizeof(struct atl1c_tpd_desc));
+	return	tpd_desc;
+}
+
+static struct atl1c_buffer *
+atl1c_get_tx_buffer(struct atl1c_adapter *adapter, struct atl1c_tpd_desc *tpd)
+{
+	struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring;
+
+	return &tpd_ring->buffer_info[tpd -
+			(struct atl1c_tpd_desc *)tpd_ring->desc];
+}
+
+/* Calculate the transmit packet descript needed*/
+static u16 atl1c_cal_tpd_req(const struct sk_buff *skb)
+{
+	u16 tpd_req;
+	u16 proto_hdr_len = 0;
+
+	tpd_req = skb_shinfo(skb)->nr_frags + 1;
+
+	if (skb_is_gso(skb)) {
+		proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+		if (proto_hdr_len < skb_headlen(skb))
+			tpd_req++;
+		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+			tpd_req++;
+	}
+	return tpd_req;
+}
+
+static int atl1c_tso_csum(struct atl1c_adapter *adapter,
+			  struct sk_buff *skb,
+			  struct atl1c_tpd_desc **tpd,
+			  enum atl1c_trans_queue type)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	u8 hdr_len;
+	u32 real_len;
+	unsigned short offload_type;
+	int err;
+
+	if (skb_is_gso(skb)) {
+		if (skb_header_cloned(skb)) {
+			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+			if (unlikely(err))
+				return -1;
+		}
+		offload_type = skb_shinfo(skb)->gso_type;
+
+		if (offload_type & SKB_GSO_TCPV4) {
+			real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
+					+ ntohs(ip_hdr(skb)->tot_len));
+
+			if (real_len < skb->len)
+				pskb_trim(skb, real_len);
+
+			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+			if (unlikely(skb->len == hdr_len)) {
+				/* only xsum need */
+				if (netif_msg_tx_queued(adapter))
+					dev_warn(&pdev->dev,
+						"IPV4 tso with zero data??\n");
+				goto check_sum;
+			} else {
+				ip_hdr(skb)->check = 0;
+				tcp_hdr(skb)->check = ~csum_tcpudp_magic(
+							ip_hdr(skb)->saddr,
+							ip_hdr(skb)->daddr,
+							0, IPPROTO_TCP, 0);
+				(*tpd)->word1 |= 1 << TPD_IPV4_PACKET_SHIFT;
+			}
+		}
+
+		if (offload_type & SKB_GSO_TCPV6) {
+			struct atl1c_tpd_ext_desc *etpd =
+				*(struct atl1c_tpd_ext_desc **)(tpd);
+
+			memset(etpd, 0, sizeof(struct atl1c_tpd_ext_desc));
+			*tpd = atl1c_get_tpd(adapter, type);
+			ipv6_hdr(skb)->payload_len = 0;
+			/* check payload == 0 byte ? */
+			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
+			if (unlikely(skb->len == hdr_len)) {
+				/* only xsum need */
+				if (netif_msg_tx_queued(adapter))
+					dev_warn(&pdev->dev,
+						"IPV6 tso with zero data??\n");
+				goto check_sum;
+			} else
+				tcp_hdr(skb)->check = ~csum_ipv6_magic(
+						&ipv6_hdr(skb)->saddr,
+						&ipv6_hdr(skb)->daddr,
+						0, IPPROTO_TCP, 0);
+			etpd->word1 |= 1 << TPD_LSO_EN_SHIFT;
+			etpd->word1 |= 1 << TPD_LSO_VER_SHIFT;
+			etpd->pkt_len = cpu_to_le32(skb->len);
+			(*tpd)->word1 |= 1 << TPD_LSO_VER_SHIFT;
+		}
+
+		(*tpd)->word1 |= 1 << TPD_LSO_EN_SHIFT;
+		(*tpd)->word1 |= (skb_transport_offset(skb) & TPD_TCPHDR_OFFSET_MASK) <<
+				TPD_TCPHDR_OFFSET_SHIFT;
+		(*tpd)->word1 |= (skb_shinfo(skb)->gso_size & TPD_MSS_MASK) <<
+				TPD_MSS_SHIFT;
+		return 0;
+	}
+
+check_sum:
+	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+		u8 css, cso;
+		cso = skb_transport_offset(skb);
+
+		if (unlikely(cso & 0x1)) {
+			if (netif_msg_tx_err(adapter))
+				dev_err(&adapter->pdev->dev,
+					"payload offset should not an event number\n");
+			return -1;
+		} else {
+			css = cso + skb->csum_offset;
+
+			(*tpd)->word1 |= ((cso >> 1) & TPD_PLOADOFFSET_MASK) <<
+					TPD_PLOADOFFSET_SHIFT;
+			(*tpd)->word1 |= ((css >> 1) & TPD_CCSUM_OFFSET_MASK) <<
+					TPD_CCSUM_OFFSET_SHIFT;
+			(*tpd)->word1 |= 1 << TPD_CCSUM_EN_SHIFT;
+		}
+	}
+	return 0;
+}
+
+static void atl1c_tx_map(struct atl1c_adapter *adapter,
+		      struct sk_buff *skb, struct atl1c_tpd_desc *tpd,
+			enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_desc *use_tpd = NULL;
+	struct atl1c_buffer *buffer_info = NULL;
+	u16 buf_len = skb_headlen(skb);
+	u16 map_len = 0;
+	u16 mapped_len = 0;
+	u16 hdr_len = 0;
+	u16 nr_frags;
+	u16 f;
+	int tso;
+
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	tso = (tpd->word1 >> TPD_LSO_EN_SHIFT) & TPD_LSO_EN_MASK;
+	if (tso) {
+		/* TSO */
+		map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+		use_tpd = tpd;
+
+		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
+		buffer_info->length = map_len;
+		buffer_info->dma = pci_map_single(adapter->pdev,
+					skb->data, hdr_len, PCI_DMA_TODEVICE);
+		buffer_info->state = ATL1_BUFFER_BUSY;
+		mapped_len += map_len;
+		use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+		use_tpd->buffer_len = cpu_to_le16(buffer_info->length);
+	}
+
+	if (mapped_len < buf_len) {
+		/* mapped_len == 0, means we should use the first tpd,
+		   which is given by caller  */
+		if (mapped_len == 0)
+			use_tpd = tpd;
+		else {
+			use_tpd = atl1c_get_tpd(adapter, type);
+			memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
+			use_tpd = atl1c_get_tpd(adapter, type);
+			memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
+		}
+		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
+		buffer_info->length = buf_len - mapped_len;
+		buffer_info->dma =
+			pci_map_single(adapter->pdev, skb->data + mapped_len,
+					buffer_info->length, PCI_DMA_TODEVICE);
+		buffer_info->state = ATL1_BUFFER_BUSY;
+
+		use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+		use_tpd->buffer_len  = cpu_to_le16(buffer_info->length);
+	}
+
+	for (f = 0; f < nr_frags; f++) {
+		struct skb_frag_struct *frag;
+
+		frag = &skb_shinfo(skb)->frags[f];
+
+		use_tpd = atl1c_get_tpd(adapter, type);
+		memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc));
+
+		buffer_info = atl1c_get_tx_buffer(adapter, use_tpd);
+		buffer_info->length = frag->size;
+		buffer_info->dma =
+			pci_map_page(adapter->pdev, frag->page,
+					frag->page_offset,
+					buffer_info->length,
+					PCI_DMA_TODEVICE);
+		buffer_info->state = ATL1_BUFFER_BUSY;
+
+		use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma);
+		use_tpd->buffer_len  = cpu_to_le16(buffer_info->length);
+	}
+
+	/* The last tpd */
+	use_tpd->word1 |= 1 << TPD_EOP_SHIFT;
+	/* The last buffer info contain the skb address,
+	   so it will be free after unmap */
+	buffer_info->skb = skb;
+}
+
+static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb,
+			   struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type)
+{
+	struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type];
+	u32 prod_data;
+
+	AT_READ_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, &prod_data);
+	switch (type) {
+	case atl1c_trans_high:
+		prod_data &= 0xFFFF0000;
+		prod_data |= tpd_ring->next_to_use & 0xFFFF;
+		break;
+	case atl1c_trans_normal:
+		prod_data &= 0x0000FFFF;
+		prod_data |= (tpd_ring->next_to_use & 0xFFFF) << 16;
+		break;
+	default:
+		break;
+	}
+	wmb();
+	AT_WRITE_REG(&adapter->hw, REG_MB_PRIO_PROD_IDX, prod_data);
+}
+
+static int atl1c_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	unsigned long flags;
+	u16 tpd_req = 1;
+	struct atl1c_tpd_desc *tpd;
+	enum atl1c_trans_queue type = atl1c_trans_normal;
+
+	if (test_bit(__AT_DOWN, &adapter->flags)) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	tpd_req = atl1c_cal_tpd_req(skb);
+	if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
+		if (netif_msg_pktdata(adapter))
+			dev_info(&adapter->pdev->dev, "tx locked\n");
+		return NETDEV_TX_LOCKED;
+	}
+	if (skb->mark == 0x01)
+		type = atl1c_trans_high;
+	else
+		type = atl1c_trans_normal;
+
+	if (atl1c_tpd_avail(adapter, type) < tpd_req) {
+		/* no enough descriptor, just stop queue */
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+
+	tpd = atl1c_get_tpd(adapter, type);
+
+	/* do TSO and check sum */
+	if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) {
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+		u16 vlan = vlan_tx_tag_get(skb);
+		__le16 tag;
+
+		vlan = cpu_to_le16(vlan);
+		AT_VLAN_TO_TAG(vlan, tag);
+		tpd->word1 |= 1 << TPD_INS_VTAG_SHIFT;
+		tpd->vlan_tag = tag;
+	}
+
+	if (skb_network_offset(skb) != ETH_HLEN)
+		tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */
+
+	atl1c_tx_map(adapter, skb, tpd, type);
+	atl1c_tx_queue(adapter, skb, tpd, type);
+
+	netdev->trans_start = jiffies;
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+	return NETDEV_TX_OK;
+}
+
+static void atl1c_free_irq(struct atl1c_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	free_irq(adapter->pdev->irq, netdev);
+
+	if (adapter->have_msi)
+		pci_disable_msi(adapter->pdev);
+}
+
+static int atl1c_request_irq(struct atl1c_adapter *adapter)
+{
+	struct pci_dev    *pdev   = adapter->pdev;
+	struct net_device *netdev = adapter->netdev;
+	int flags = 0;
+	int err = 0;
+
+	adapter->have_msi = true;
+	err = pci_enable_msi(adapter->pdev);
+	if (err) {
+		if (netif_msg_ifup(adapter))
+			dev_err(&pdev->dev,
+				"Unable to allocate MSI interrupt Error: %d\n",
+				err);
+		adapter->have_msi = false;
+	} else
+		netdev->irq = pdev->irq;
+
+	if (!adapter->have_msi)
+		flags |= IRQF_SHARED;
+	err = request_irq(adapter->pdev->irq, &atl1c_intr, flags,
+			netdev->name, netdev);
+	if (err) {
+		if (netif_msg_ifup(adapter))
+			dev_err(&pdev->dev,
+				"Unable to allocate interrupt Error: %d\n",
+				err);
+		if (adapter->have_msi)
+			pci_disable_msi(adapter->pdev);
+		return err;
+	}
+	if (netif_msg_ifup(adapter))
+		dev_dbg(&pdev->dev, "atl1c_request_irq OK\n");
+	return err;
+}
+
+int atl1c_up(struct atl1c_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	int num;
+	int err;
+	int i;
+
+	netif_carrier_off(netdev);
+	atl1c_init_ring_ptrs(adapter);
+	atl1c_set_multi(netdev);
+	atl1c_restore_vlan(adapter);
+
+	for (i = 0; i < adapter->num_rx_queues; i++) {
+		num = atl1c_alloc_rx_buffer(adapter, i);
+		if (unlikely(num == 0)) {
+			err = -ENOMEM;
+			goto err_alloc_rx;
+		}
+	}
+
+	if (atl1c_configure(adapter)) {
+		err = -EIO;
+		goto err_up;
+	}
+
+	err = atl1c_request_irq(adapter);
+	if (unlikely(err))
+		goto err_up;
+
+	clear_bit(__AT_DOWN, &adapter->flags);
+	napi_enable(&adapter->napi);
+	atl1c_irq_enable(adapter);
+	atl1c_check_link_status(adapter);
+	netif_start_queue(netdev);
+	return err;
+
+err_up:
+err_alloc_rx:
+	atl1c_clean_rx_ring(adapter);
+	return err;
+}
+
+void atl1c_down(struct atl1c_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+
+	atl1c_del_timer(adapter);
+	atl1c_cancel_work(adapter);
+
+	/* signal that we're down so the interrupt handler does not
+	 * reschedule our watchdog timer */
+	set_bit(__AT_DOWN, &adapter->flags);
+	netif_carrier_off(netdev);
+	napi_disable(&adapter->napi);
+	atl1c_irq_disable(adapter);
+	atl1c_free_irq(adapter);
+	AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT);
+	/* reset MAC to disable all RX/TX */
+	atl1c_reset_mac(&adapter->hw);
+	msleep(1);
+
+	adapter->link_speed = SPEED_0;
+	adapter->link_duplex = -1;
+	atl1c_clean_tx_ring(adapter, atl1c_trans_normal);
+	atl1c_clean_tx_ring(adapter, atl1c_trans_high);
+	atl1c_clean_rx_ring(adapter);
+}
+
+/*
+ * atl1c_open - Called when a network interface is made active
+ * @netdev: network interface device structure
+ *
+ * Returns 0 on success, negative value on failure
+ *
+ * The open entry point is called when a network interface is made
+ * active by the system (IFF_UP).  At this point all resources needed
+ * for transmit and receive operations are allocated, the interrupt
+ * handler is registered with the OS, the watchdog timer is started,
+ * and the stack is notified that the interface is ready.
+ */
+static int atl1c_open(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	int err;
+
+	/* disallow open during test */
+	if (test_bit(__AT_TESTING, &adapter->flags))
+		return -EBUSY;
+
+	/* allocate rx/tx dma buffer & descriptors */
+	err = atl1c_setup_ring_resources(adapter);
+	if (unlikely(err))
+		return err;
+
+	err = atl1c_up(adapter);
+	if (unlikely(err))
+		goto err_up;
+
+	if (adapter->hw.ctrl_flags & ATL1C_FPGA_VERSION) {
+		u32 phy_data;
+
+		AT_READ_REG(&adapter->hw, REG_MDIO_CTRL, &phy_data);
+		phy_data |= MDIO_AP_EN;
+		AT_WRITE_REG(&adapter->hw, REG_MDIO_CTRL, phy_data);
+	}
+	return 0;
+
+err_up:
+	atl1c_free_irq(adapter);
+	atl1c_free_ring_resources(adapter);
+	atl1c_reset_mac(&adapter->hw);
+	return err;
+}
+
+/*
+ * atl1c_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ */
+static int atl1c_close(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+	atl1c_down(adapter);
+	atl1c_free_ring_resources(adapter);
+	return 0;
+}
+
+static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+	u32 ctrl;
+	u32 mac_ctrl_data;
+	u32 master_ctrl_data;
+	u32 wol_ctrl_data;
+	u16 mii_bmsr_data;
+	u16 save_autoneg_advertised;
+	u16 mii_intr_status_data;
+	u32 wufc = adapter->wol;
+	u32 i;
+	int retval = 0;
+
+	if (netif_running(netdev)) {
+		WARN_ON(test_bit(__AT_RESETTING, &adapter->flags));
+		atl1c_down(adapter);
+	}
+	netif_device_detach(netdev);
+	atl1c_disable_l0s_l1(hw);
+	retval = pci_save_state(pdev);
+	if (retval)
+		return retval;
+	if (wufc) {
+		AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data);
+		master_ctrl_data &= ~MASTER_CTRL_CLK_SEL_DIS;
+
+		/* get link status */
+		atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+		atl1c_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
+		save_autoneg_advertised = hw->autoneg_advertised;
+		hw->autoneg_advertised = ADVERTISED_10baseT_Half;
+		if (atl1c_restart_autoneg(hw) != 0)
+			if (netif_msg_link(adapter))
+				dev_warn(&pdev->dev, "phy autoneg failed\n");
+		hw->phy_configured = false; /* re-init PHY when resume */
+		hw->autoneg_advertised = save_autoneg_advertised;
+		/* turn on magic packet wol */
+		if (wufc & AT_WUFC_MAG)
+			wol_ctrl_data = WOL_MAGIC_EN | WOL_MAGIC_PME_EN;
+
+		if (wufc & AT_WUFC_LNKC) {
+			for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) {
+				msleep(100);
+				atl1c_read_phy_reg(hw, MII_BMSR,
+					(u16 *)&mii_bmsr_data);
+				if (mii_bmsr_data & BMSR_LSTATUS)
+					break;
+			}
+			if ((mii_bmsr_data & BMSR_LSTATUS) == 0)
+				if (netif_msg_link(adapter))
+					dev_warn(&pdev->dev,
+						"%s: Link may change"
+						"when suspend\n",
+						atl1c_driver_name);
+			wol_ctrl_data |=  WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN;
+			/* only link up can wake up */
+			if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) {
+				if (netif_msg_link(adapter))
+					dev_err(&pdev->dev,
+						"%s: read write phy "
+						"register failed.\n",
+						atl1c_driver_name);
+				goto wol_dis;
+			}
+		}
+		/* clear phy interrupt */
+		atl1c_read_phy_reg(hw, MII_ISR, &mii_intr_status_data);
+		/* Config MAC Ctrl register */
+		mac_ctrl_data = MAC_CTRL_RX_EN;
+		/* set to 10/100M halt duplex */
+		mac_ctrl_data |= atl1c_mac_speed_10_100 << MAC_CTRL_SPEED_SHIFT;
+		mac_ctrl_data |= (((u32)adapter->hw.preamble_len &
+				 MAC_CTRL_PRMLEN_MASK) <<
+				 MAC_CTRL_PRMLEN_SHIFT);
+
+		if (adapter->vlgrp)
+			mac_ctrl_data |= MAC_CTRL_RMV_VLAN;
+
+		/* magic packet maybe Broadcast&multicast&Unicast frame */
+		if (wufc & AT_WUFC_MAG)
+			mac_ctrl_data |= MAC_CTRL_BC_EN;
+
+		if (netif_msg_hw(adapter))
+			dev_dbg(&pdev->dev,
+				"%s: suspend MAC=0x%x\n",
+				atl1c_driver_name, mac_ctrl_data);
+		AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data);
+		AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
+		AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
+
+		/* pcie patch */
+		AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl);
+		ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+		AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+
+		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
+		goto suspend_exit;
+	}
+wol_dis:
+
+	/* WOL disabled */
+	AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
+
+	/* pcie patch */
+	AT_READ_REG(hw, REG_PCIE_PHYMISC, &ctrl);
+	ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
+	AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl);
+
+	atl1c_phy_disable(hw);
+	hw->phy_configured = false; /* re-init PHY when resume */
+
+	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+suspend_exit:
+
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+static int atl1c_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
+
+	atl1c_phy_reset(&adapter->hw);
+	atl1c_reset_mac(&adapter->hw);
+	netif_device_attach(netdev);
+	if (netif_running(netdev))
+		atl1c_up(adapter);
+
+	return 0;
+}
+
+static void atl1c_shutdown(struct pci_dev *pdev)
+{
+	atl1c_suspend(pdev, PMSG_SUSPEND);
+}
+
+static const struct net_device_ops atl1c_netdev_ops = {
+	.ndo_open		= atl1c_open,
+	.ndo_stop		= atl1c_close,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_start_xmit		= atl1c_xmit_frame,
+	.ndo_set_mac_address 	= atl1c_set_mac_addr,
+	.ndo_set_multicast_list = atl1c_set_multi,
+	.ndo_change_mtu		= atl1c_change_mtu,
+	.ndo_do_ioctl		= atl1c_ioctl,
+	.ndo_tx_timeout		= atl1c_tx_timeout,
+	.ndo_get_stats		= atl1c_get_stats,
+	.ndo_vlan_rx_register	= atl1c_vlan_rx_register,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller	= atl1c_netpoll,
+#endif
+};
+
+static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
+{
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+	pci_set_drvdata(pdev, netdev);
+
+	netdev->irq  = pdev->irq;
+	netdev->netdev_ops = &atl1c_netdev_ops;
+	netdev->watchdog_timeo = AT_TX_WATCHDOG;
+	atl1c_set_ethtool_ops(netdev);
+
+	/* TODO: add when ready */
+	netdev->features =	NETIF_F_SG	   |
+				NETIF_F_HW_CSUM	   |
+				NETIF_F_HW_VLAN_TX |
+				NETIF_F_HW_VLAN_RX |
+				NETIF_F_TSO	   |
+				NETIF_F_TSO6;
+	return 0;
+}
+
+/*
+ * atl1c_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in atl1c_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * atl1c_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ */
+static int __devinit atl1c_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	struct net_device *netdev;
+	struct atl1c_adapter *adapter;
+	static int cards_found;
+
+	int err = 0;
+
+	/* enable device (incl. PCI PM wakeup and hotplug setup) */
+	err = pci_enable_device_mem(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "cannot enable PCI device\n");
+		return err;
+	}
+
+	/*
+	 * The atl1c chip can DMA to 64-bit addresses, but it uses a single
+	 * shared register for the high 32 bits, so only a single, aligned,
+	 * 4 GB physical address range can be used at a time.
+	 *
+	 * Supporting 64-bit DMA on this hardware is more trouble than it's
+	 * worth.  It is far easier to limit to 32-bit DMA than update
+	 * various kernel subsystems to support the mechanics required by a
+	 * fixed-high-32-bit system.
+	 */
+	if ((pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) ||
+	    (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) != 0)) {
+		dev_err(&pdev->dev, "No usable DMA configuration,aborting\n");
+		goto err_dma;
+	}
+
+	err = pci_request_regions(pdev, atl1c_driver_name);
+	if (err) {
+		dev_err(&pdev->dev, "cannot obtain PCI resources\n");
+		goto err_pci_reg;
+	}
+
+	pci_set_master(pdev);
+
+	netdev = alloc_etherdev(sizeof(struct atl1c_adapter));
+	if (netdev == NULL) {
+		err = -ENOMEM;
+		dev_err(&pdev->dev, "etherdev alloc failed\n");
+		goto err_alloc_etherdev;
+	}
+
+	err = atl1c_init_netdev(netdev, pdev);
+	if (err) {
+		dev_err(&pdev->dev, "init netdevice failed\n");
+		goto err_init_netdev;
+	}
+	adapter = netdev_priv(netdev);
+	adapter->bd_number = cards_found;
+	adapter->netdev = netdev;
+	adapter->pdev = pdev;
+	adapter->hw.adapter = adapter;
+	adapter->msg_enable = netif_msg_init(-1, atl1c_default_msg);
+	adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+	if (!adapter->hw.hw_addr) {
+		err = -EIO;
+		dev_err(&pdev->dev, "cannot map device registers\n");
+		goto err_ioremap;
+	}
+	netdev->base_addr = (unsigned long)adapter->hw.hw_addr;
+
+	/* init mii data */
+	adapter->mii.dev = netdev;
+	adapter->mii.mdio_read  = atl1c_mdio_read;
+	adapter->mii.mdio_write = atl1c_mdio_write;
+	adapter->mii.phy_id_mask = 0x1f;
+	adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK;
+	netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64);
+	setup_timer(&adapter->phy_config_timer, atl1c_phy_config,
+			(unsigned long)adapter);
+	/* setup the private structure */
+	err = atl1c_sw_init(adapter);
+	if (err) {
+		dev_err(&pdev->dev, "net device private data init failed\n");
+		goto err_sw_init;
+	}
+	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
+			ATL1C_PCIE_PHY_RESET);
+
+	/* Init GPHY as early as possible due to power saving issue  */
+	atl1c_phy_reset(&adapter->hw);
+
+	err = atl1c_reset_mac(&adapter->hw);
+	if (err) {
+		err = -EIO;
+		goto err_reset;
+	}
+
+	device_init_wakeup(&pdev->dev, 1);
+	/* reset the controller to
+	 * put the device in a known good starting state */
+	err = atl1c_phy_init(&adapter->hw);
+	if (err) {
+		err = -EIO;
+		goto err_reset;
+	}
+	if (atl1c_read_mac_addr(&adapter->hw) != 0) {
+		err = -EIO;
+		dev_err(&pdev->dev, "get mac address failed\n");
+		goto err_eeprom;
+	}
+	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
+	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
+	if (netif_msg_probe(adapter))
+		dev_dbg(&pdev->dev,
+			"mac address : %02x-%02x-%02x-%02x-%02x-%02x\n",
+			adapter->hw.mac_addr[0], adapter->hw.mac_addr[1],
+			adapter->hw.mac_addr[2], adapter->hw.mac_addr[3],
+			adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]);
+
+	atl1c_hw_set_mac_addr(&adapter->hw);
+	INIT_WORK(&adapter->reset_task, atl1c_reset_task);
+	INIT_WORK(&adapter->link_chg_task, atl1c_link_chg_task);
+	err = register_netdev(netdev);
+	if (err) {
+		dev_err(&pdev->dev, "register netdevice failed\n");
+		goto err_register;
+	}
+
+	if (netif_msg_probe(adapter))
+		dev_info(&pdev->dev, "version %s\n", ATL1C_DRV_VERSION);
+	cards_found++;
+	return 0;
+
+err_reset:
+err_register:
+err_sw_init:
+err_eeprom:
+	iounmap(adapter->hw.hw_addr);
+err_init_netdev:
+err_ioremap:
+	free_netdev(netdev);
+err_alloc_etherdev:
+	pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+	pci_disable_device(pdev);
+	return err;
+}
+
+/*
+ * atl1c_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * atl1c_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ */
+static void __devexit atl1c_remove(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	unregister_netdev(netdev);
+	atl1c_phy_disable(&adapter->hw);
+
+	iounmap(adapter->hw.hw_addr);
+
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	free_netdev(netdev);
+}
+
+/*
+ * atl1c_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev,
+						pci_channel_state_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	netif_device_detach(netdev);
+
+	if (netif_running(netdev))
+		atl1c_down(adapter);
+
+	pci_disable_device(pdev);
+
+	/* Request a slot slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/*
+ * atl1c_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t atl1c_io_slot_reset(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	if (pci_enable_device(pdev)) {
+		if (netif_msg_hw(adapter))
+			dev_err(&pdev->dev,
+				"Cannot re-enable PCI device after reset\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	pci_set_master(pdev);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	atl1c_reset_mac(&adapter->hw);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/*
+ * atl1c_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the atl1c_resume routine.
+ */
+static void atl1c_io_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+	if (netif_running(netdev)) {
+		if (atl1c_up(adapter)) {
+			if (netif_msg_hw(adapter))
+				dev_err(&pdev->dev,
+					"Cannot bring device back up after reset\n");
+			return;
+		}
+	}
+
+	netif_device_attach(netdev);
+}
+
+static struct pci_error_handlers atl1c_err_handler = {
+	.error_detected = atl1c_io_error_detected,
+	.slot_reset = atl1c_io_slot_reset,
+	.resume = atl1c_io_resume,
+};
+
+static struct pci_driver atl1c_driver = {
+	.name     = atl1c_driver_name,
+	.id_table = atl1c_pci_tbl,
+	.probe    = atl1c_probe,
+	.remove   = __devexit_p(atl1c_remove),
+	/* Power Managment Hooks */
+	.suspend  = atl1c_suspend,
+	.resume   = atl1c_resume,
+	.shutdown = atl1c_shutdown,
+	.err_handler = &atl1c_err_handler
+};
+
+/*
+ * atl1c_init_module - Driver Registration Routine
+ *
+ * atl1c_init_module is the first routine called when the driver is
+ * loaded. All it does is register with the PCI subsystem.
+ */
+static int __init atl1c_init_module(void)
+{
+	return pci_register_driver(&atl1c_driver);
+}
+
+/*
+ * atl1c_exit_module - Driver Exit Cleanup Routine
+ *
+ * atl1c_exit_module is called just before the driver is removed
+ * from memory.
+ */
+static void __exit atl1c_exit_module(void)
+{
+	pci_unregister_driver(&atl1c_driver);
+}
+
+module_init(atl1c_init_module);
+module_exit(atl1c_exit_module);
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 0089746..bab8a93 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -90,6 +90,7 @@
 	CH_DEVICE(0x30, 2),	/* T3B10 */
 	CH_DEVICE(0x31, 3),	/* T3B20 */
 	CH_DEVICE(0x32, 1),	/* T3B02 */
+	CH_DEVICE(0x35, 6),	/* T3C20-derived T3C10 */
 	{0,}
 };
 
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 2d14330..ac2a974 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -512,6 +512,13 @@
 	 F_GPIO5_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
 	 { S_GPIO9, S_GPIO3 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
 	 &mi1_mdio_ext_ops, "Chelsio T320"},
+	{},
+	{},
+	{1, 0,
+	 F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
+	 F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
+	 { S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
+	 &mi1_mdio_ext_ops, "Chelsio T310" },
 };
 
 /*
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 5b910cf..b8251e8 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -6011,9 +6011,20 @@
 	if (netif_running(dev))
 		nv_close(dev);
 
-	nv_restore_mac_addr(pdev);
+	/*
+	 * Restore the MAC so a kernel started by kexec won't get confused.
+	 * If we really go for poweroff, we must not restore the MAC,
+	 * otherwise the MAC for WOL will be reversed at least on some boards.
+	 */
+	if (system_state != SYSTEM_POWER_OFF) {
+		nv_restore_mac_addr(pdev);
+	}
 
 	pci_disable_device(pdev);
+	/*
+	 * Apparently it is not possible to reinitialise from D3 hot,
+	 * only put the device into D3 if we really go for poweroff.
+	 */
 	if (system_state == SYSTEM_POWER_OFF) {
 		if (pci_enable_wake(pdev, PCI_D3cold, np->wolenabled))
 			pci_enable_wake(pdev, PCI_D3hot, np->wolenabled);
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 5f31bbb..13f11f4 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1175,7 +1175,7 @@
 {
 	struct mib_counters *p = &mp->mib_counters;
 
-	spin_lock(&mp->mib_counters_lock);
+	spin_lock_bh(&mp->mib_counters_lock);
 	p->good_octets_received += mib_read(mp, 0x00);
 	p->good_octets_received += (u64)mib_read(mp, 0x04) << 32;
 	p->bad_octets_received += mib_read(mp, 0x08);
@@ -1208,7 +1208,7 @@
 	p->bad_crc_event += mib_read(mp, 0x74);
 	p->collision += mib_read(mp, 0x78);
 	p->late_collision += mib_read(mp, 0x7c);
-	spin_unlock(&mp->mib_counters_lock);
+	spin_unlock_bh(&mp->mib_counters_lock);
 
 	mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
 }
@@ -1575,7 +1575,7 @@
 		return;
 	}
 
-	mc_spec = kmalloc(0x200, GFP_KERNEL);
+	mc_spec = kmalloc(0x200, GFP_ATOMIC);
 	if (mc_spec == NULL)
 		goto oom;
 	mc_other = mc_spec + (0x100 >> 2);
@@ -2216,8 +2216,6 @@
 	wrlp(mp, INT_MASK, 0x00000000);
 	rdlp(mp, INT_MASK);
 
-	del_timer_sync(&mp->mib_counters_timer);
-
 	napi_disable(&mp->napi);
 
 	del_timer_sync(&mp->rx_oom);
@@ -2229,6 +2227,7 @@
 	port_reset(mp);
 	mv643xx_eth_get_stats(dev);
 	mib_counters_update(mp);
+	del_timer_sync(&mp->mib_counters_timer);
 
 	skb_queue_purge(&mp->rx_recycle);
 
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index 783c1a7..9a78dae 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -1624,7 +1624,7 @@
 	do {
 		msleep(1);
 		e2cmd = smsc911x_reg_read(pdata, E2P_CMD);
-	} while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--));
+	} while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout));
 
 	if (!timeout) {
 		SMSC_TRACE(DRV, "TIMED OUT");
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
index a1e4b38..4e15ae0 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/smsc9420.c
@@ -341,7 +341,7 @@
 	do {
 		msleep(1);
 		e2cmd = smsc9420_reg_read(pd, E2P_CMD);
-	} while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--));
+	} while ((e2cmd & E2P_CMD_EPC_BUSY_) && (--timeout));
 
 	if (!timeout) {
 		smsc_info(HW, "TIMED OUT");
@@ -413,6 +413,7 @@
 	}
 
 	memcpy(data, &eeprom_data[eeprom->offset], len);
+	eeprom->magic = SMSC9420_EEPROM_MAGIC;
 	eeprom->len = len;
 	return 0;
 }
@@ -423,6 +424,9 @@
 	struct smsc9420_pdata *pd = netdev_priv(dev);
 	int ret;
 
+	if (eeprom->magic != SMSC9420_EEPROM_MAGIC)
+		return -EINVAL;
+
 	smsc9420_eeprom_enable_access(pd);
 	smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_);
 	ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data);
diff --git a/drivers/net/smsc9420.h b/drivers/net/smsc9420.h
index 69c351f..e441402 100644
--- a/drivers/net/smsc9420.h
+++ b/drivers/net/smsc9420.h
@@ -44,6 +44,7 @@
 #define LAN_REGISTER_EXTENT		(0x400)
 
 #define SMSC9420_EEPROM_SIZE		((u32)11)
+#define SMSC9420_EEPROM_MAGIC		(0x9420)
 
 #define PKT_BUF_SZ			(VLAN_ETH_FRAME_LEN + NET_IP_ALIGN + 4)
 
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index feaf0e0..43695b7 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -909,7 +909,7 @@
 			printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d "
 				   "negotiated capability %4.4x.\n", dev->name,
 				   duplex ? "full" : "half", np->phys[0], negotiated);
-		iowrite16(ioread16(ioaddr + MACCtrl0) | duplex ? 0x20 : 0, ioaddr + MACCtrl0);
+		iowrite16(ioread16(ioaddr + MACCtrl0) | (duplex ? 0x20 : 0), ioaddr + MACCtrl0);
 	}
 }
 
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 4918763..8d64b1d 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -1157,7 +1157,7 @@
 		if (limit-- <= 0)
 			break;
 	}
-	if (limit <= 0)
+	if (limit < 0)
 		printk(KERN_WARNING "%s: PCS reset bit would not clear.\n",
 		       gp->dev->name);
 }
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 2813732..16c528d 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -343,7 +343,7 @@
 	ib->phys_addr [5] = dev->dev_addr [4];
 
 	/* Setup the Tx ring entries */
-	for (i = 0; i <= TX_RING_SIZE; i++) {
+	for (i = 0; i < TX_RING_SIZE; i++) {
 		leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i));
 		ib->btx_ring [i].tmd0      = leptr;
 		ib->btx_ring [i].tmd1_hadr = leptr >> 16;
@@ -399,7 +399,7 @@
 	sbus_writeb(dev->dev_addr[4], &ib->phys_addr[5]);
 
 	/* Setup the Tx ring entries */
-	for (i = 0; i <= TX_RING_SIZE; i++) {
+	for (i = 0; i < TX_RING_SIZE; i++) {
 		leptr = libbuff_offset(tx_buf, i);
 		sbus_writew(leptr,	&ib->btx_ring [i].tmd0);
 		sbus_writeb(leptr >> 16,&ib->btx_ring [i].tmd1_hadr);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 4595962..b080f94 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -2237,8 +2237,8 @@
 			phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
 			if (phyid != TG3_PHY_ID_BCMAC131) {
 				phyid &= TG3_PHY_OUI_MASK;
-				if (phyid == TG3_PHY_OUI_1 &&
-				    phyid == TG3_PHY_OUI_2 &&
+				if (phyid == TG3_PHY_OUI_1 ||
+				    phyid == TG3_PHY_OUI_2 ||
 				    phyid == TG3_PHY_OUI_3)
 					do_low_power = true;
 			}
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 852d0e7..108bbbe 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -263,10 +263,11 @@
 }
 
 static const struct net_device_ops veth_netdev_ops = {
-	.ndo_init	= veth_dev_init,
-	.ndo_open	= veth_open,
-	.ndo_start_xmit = veth_xmit,
-	.ndo_get_stats	= veth_get_stats,
+	.ndo_init            = veth_dev_init,
+	.ndo_open            = veth_open,
+	.ndo_start_xmit      = veth_xmit,
+	.ndo_get_stats       = veth_get_stats,
+	.ndo_set_mac_address = eth_mac_addr,
 };
 
 static void veth_setup(struct net_device *dev)
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index 067c871..3b9d27e 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -157,7 +157,7 @@
 
 
 /* Firmware version we request when pulling the fw image file */
-#define I2400M_FW_VERSION "1.3"
+#define I2400M_FW_VERSION "1.4"
 
 
 /**
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index b0ee86c..ab13ff2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -148,7 +148,7 @@
 		pci_unmap_single(dev,
 				pci_unmap_addr(&txq->cmd[index]->meta, mapping),
 				pci_unmap_len(&txq->cmd[index]->meta, len),
-				PCI_DMA_TODEVICE);
+				PCI_DMA_BIDIRECTIONAL);
 
 	/* Unmap chunks, if any. */
 	for (i = 1; i < num_tbs; i++) {
@@ -964,7 +964,7 @@
 	 * within command buffer array. */
 	txcmd_phys = pci_map_single(priv->pci_dev,
 				    out_cmd, sizeof(struct iwl_cmd),
-				    PCI_DMA_TODEVICE);
+				    PCI_DMA_BIDIRECTIONAL);
 	pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
 	pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
 	/* Add buffer containing Tx command and MAC(!) header to TFD's
@@ -1115,7 +1115,7 @@
 			IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
 
 	phys_addr = pci_map_single(priv->pci_dev, out_cmd,
-				   len, PCI_DMA_TODEVICE);
+				   len, PCI_DMA_BIDIRECTIONAL);
 	pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
 	pci_unmap_len_set(&out_cmd->meta, len, len);
 	phys_addr += offsetof(struct iwl_cmd, hdr);
@@ -1212,7 +1212,7 @@
 	pci_unmap_single(priv->pci_dev,
 		pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping),
 		pci_unmap_len(&txq->cmd[cmd_idx]->meta, len),
-		PCI_DMA_TODEVICE);
+		PCI_DMA_BIDIRECTIONAL);
 
 	for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
 	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 519f5f9..5f33340 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -332,6 +332,14 @@
 	entry_header = (struct acpi_dmar_header *)(dmar + 1);
 	while (((unsigned long)entry_header) <
 			(((unsigned long)dmar) + dmar_tbl->length)) {
+		/* Avoid looping forever on bad ACPI tables */
+		if (entry_header->length == 0) {
+			printk(KERN_WARNING PREFIX
+				"Invalid 0-length structure\n");
+			ret = -EINVAL;
+			break;
+		}
+
 		dmar_table_print_dmar_entry(entry_header);
 
 		switch (entry_header->type) {
@@ -494,7 +502,7 @@
 	int map_size;
 	u32 ver;
 	static int iommu_allocated = 0;
-	int agaw;
+	int agaw = 0;
 
 	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
 	if (!iommu)
@@ -510,6 +518,7 @@
 	iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
 	iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
 
+#ifdef CONFIG_DMAR
 	agaw = iommu_calculate_agaw(iommu);
 	if (agaw < 0) {
 		printk(KERN_ERR
@@ -517,6 +526,7 @@
 			iommu->seq_id);
 		goto error;
 	}
+#endif
 	iommu->agaw = agaw;
 
 	/* the registers might be more than one page */
@@ -574,19 +584,49 @@
 	}
 }
 
+static int qi_check_fault(struct intel_iommu *iommu, int index)
+{
+	u32 fault;
+	int head;
+	struct q_inval *qi = iommu->qi;
+	int wait_index = (index + 1) % QI_LENGTH;
+
+	fault = readl(iommu->reg + DMAR_FSTS_REG);
+
+	/*
+	 * If IQE happens, the head points to the descriptor associated
+	 * with the error. No new descriptors are fetched until the IQE
+	 * is cleared.
+	 */
+	if (fault & DMA_FSTS_IQE) {
+		head = readl(iommu->reg + DMAR_IQH_REG);
+		if ((head >> 4) == index) {
+			memcpy(&qi->desc[index], &qi->desc[wait_index],
+					sizeof(struct qi_desc));
+			__iommu_flush_cache(iommu, &qi->desc[index],
+					sizeof(struct qi_desc));
+			writel(DMA_FSTS_IQE, iommu->reg + DMAR_FSTS_REG);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 /*
  * Submit the queued invalidation descriptor to the remapping
  * hardware unit and wait for its completion.
  */
-void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
+int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu)
 {
+	int rc = 0;
 	struct q_inval *qi = iommu->qi;
 	struct qi_desc *hw, wait_desc;
 	int wait_index, index;
 	unsigned long flags;
 
 	if (!qi)
-		return;
+		return 0;
 
 	hw = qi->desc;
 
@@ -604,7 +644,8 @@
 
 	hw[index] = *desc;
 
-	wait_desc.low = QI_IWD_STATUS_DATA(2) | QI_IWD_STATUS_WRITE | QI_IWD_TYPE;
+	wait_desc.low = QI_IWD_STATUS_DATA(QI_DONE) |
+			QI_IWD_STATUS_WRITE | QI_IWD_TYPE;
 	wait_desc.high = virt_to_phys(&qi->desc_status[wait_index]);
 
 	hw[wait_index] = wait_desc;
@@ -615,13 +656,11 @@
 	qi->free_head = (qi->free_head + 2) % QI_LENGTH;
 	qi->free_cnt -= 2;
 
-	spin_lock(&iommu->register_lock);
 	/*
 	 * update the HW tail register indicating the presence of
 	 * new descriptors.
 	 */
 	writel(qi->free_head << 4, iommu->reg + DMAR_IQT_REG);
-	spin_unlock(&iommu->register_lock);
 
 	while (qi->desc_status[wait_index] != QI_DONE) {
 		/*
@@ -631,15 +670,21 @@
 		 * a deadlock where the interrupt context can wait indefinitely
 		 * for free slots in the queue.
 		 */
+		rc = qi_check_fault(iommu, index);
+		if (rc)
+			goto out;
+
 		spin_unlock(&qi->q_lock);
 		cpu_relax();
 		spin_lock(&qi->q_lock);
 	}
-
-	qi->desc_status[index] = QI_DONE;
+out:
+	qi->desc_status[index] = qi->desc_status[wait_index] = QI_DONE;
 
 	reclaim_free_desc(qi);
 	spin_unlock_irqrestore(&qi->q_lock, flags);
+
+	return rc;
 }
 
 /*
@@ -652,13 +697,13 @@
 	desc.low = QI_IEC_TYPE;
 	desc.high = 0;
 
+	/* should never fail */
 	qi_submit_sync(&desc, iommu);
 }
 
 int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, u8 fm,
 		     u64 type, int non_present_entry_flush)
 {
-
 	struct qi_desc desc;
 
 	if (non_present_entry_flush) {
@@ -672,10 +717,7 @@
 			| QI_CC_GRAN(type) | QI_CC_TYPE;
 	desc.high = 0;
 
-	qi_submit_sync(&desc, iommu);
-
-	return 0;
-
+	return qi_submit_sync(&desc, iommu);
 }
 
 int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
@@ -705,10 +747,7 @@
 	desc.high = QI_IOTLB_ADDR(addr) | QI_IOTLB_IH(ih)
 		| QI_IOTLB_AM(size_order);
 
-	qi_submit_sync(&desc, iommu);
-
-	return 0;
-
+	return qi_submit_sync(&desc, iommu);
 }
 
 /*
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index db85284..39ae375 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -111,6 +111,7 @@
 	int cmd_busy;
 	unsigned int no_cmd_complete:1;
 	unsigned int link_active_reporting:1;
+	unsigned int notification_enabled:1;
 };
 
 #define INT_BUTTON_IGNORE		0
@@ -170,6 +171,7 @@
 extern int pciehp_unconfigure_device(struct slot *p_slot);
 extern void pciehp_queue_pushbutton_work(struct work_struct *work);
 struct controller *pcie_init(struct pcie_device *dev);
+int pcie_init_notification(struct controller *ctrl);
 int pciehp_enable_slot(struct slot *p_slot);
 int pciehp_disable_slot(struct slot *p_slot);
 int pcie_enable_notification(struct controller *ctrl);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index c248554..681e391 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -434,6 +434,13 @@
 		goto err_out_release_ctlr;
 	}
 
+	/* Enable events after we have setup the data structures */
+	rc = pcie_init_notification(ctrl);
+	if (rc) {
+		ctrl_err(ctrl, "Notification initialization failed\n");
+		goto err_out_release_ctlr;
+	}
+
 	/* Check if slot is occupied */
 	t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
 	t_slot->hpc_ops->get_adapter_status(t_slot, &value);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 71a8012..7a16c68 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -934,7 +934,7 @@
 		ctrl_warn(ctrl, "Cannot disable software notification\n");
 }
 
-static int pcie_init_notification(struct controller *ctrl)
+int pcie_init_notification(struct controller *ctrl)
 {
 	if (pciehp_request_irq(ctrl))
 		return -1;
@@ -942,13 +942,17 @@
 		pciehp_free_irq(ctrl);
 		return -1;
 	}
+	ctrl->notification_enabled = 1;
 	return 0;
 }
 
 static void pcie_shutdown_notification(struct controller *ctrl)
 {
-	pcie_disable_notification(ctrl);
-	pciehp_free_irq(ctrl);
+	if (ctrl->notification_enabled) {
+		pcie_disable_notification(ctrl);
+		pciehp_free_irq(ctrl);
+		ctrl->notification_enabled = 0;
+	}
 }
 
 static int pcie_init_slot(struct controller *ctrl)
@@ -1110,13 +1114,8 @@
 	if (pcie_init_slot(ctrl))
 		goto abort_ctrl;
 
-	if (pcie_init_notification(ctrl))
-		goto abort_slot;
-
 	return ctrl;
 
-abort_slot:
-	pcie_cleanup_slot(ctrl);
 abort_ctrl:
 	kfree(ctrl);
 abort:
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 5a57753..8e44db0 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -208,7 +208,7 @@
 	return index;
 }
 
-static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
+static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
 {
 	struct qi_desc desc;
 
@@ -216,7 +216,7 @@
 		   | QI_IEC_SELECTIVE;
 	desc.high = 0;
 
-	qi_submit_sync(&desc, iommu);
+	return qi_submit_sync(&desc, iommu);
 }
 
 int map_irq_to_irte_handle(int irq, u16 *sub_handle)
@@ -284,6 +284,7 @@
 
 int modify_irte(int irq, struct irte *irte_modified)
 {
+	int rc;
 	int index;
 	struct irte *irte;
 	struct intel_iommu *iommu;
@@ -304,14 +305,15 @@
 	set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1));
 	__iommu_flush_cache(iommu, irte, sizeof(*irte));
 
-	qi_flush_iec(iommu, index, 0);
-
+	rc = qi_flush_iec(iommu, index, 0);
 	spin_unlock(&irq_2_ir_lock);
-	return 0;
+
+	return rc;
 }
 
 int flush_irte(int irq)
 {
+	int rc;
 	int index;
 	struct intel_iommu *iommu;
 	struct irq_2_iommu *irq_iommu;
@@ -327,10 +329,10 @@
 
 	index = irq_iommu->irte_index + irq_iommu->sub_handle;
 
-	qi_flush_iec(iommu, index, irq_iommu->irte_mask);
+	rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
 	spin_unlock(&irq_2_ir_lock);
 
-	return 0;
+	return rc;
 }
 
 struct intel_iommu *map_ioapic_to_ir(int apic)
@@ -356,6 +358,7 @@
 
 int free_irte(int irq)
 {
+	int rc = 0;
 	int index, i;
 	struct irte *irte;
 	struct intel_iommu *iommu;
@@ -376,7 +379,7 @@
 	if (!irq_iommu->sub_handle) {
 		for (i = 0; i < (1 << irq_iommu->irte_mask); i++)
 			set_64bit((unsigned long *)irte, 0);
-		qi_flush_iec(iommu, index, irq_iommu->irte_mask);
+		rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
 	}
 
 	irq_iommu->iommu = NULL;
@@ -386,7 +389,7 @@
 
 	spin_unlock(&irq_2_ir_lock);
 
-	return 0;
+	return rc;
 }
 
 static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index aac7006..d0c9736 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -108,6 +108,34 @@
 }
 #endif  /*  0  */
 
+
+static void set_device_error_reporting(struct pci_dev *dev, void *data)
+{
+	bool enable = *((bool *)data);
+
+	if (dev->pcie_type != PCIE_RC_PORT &&
+	    dev->pcie_type != PCIE_SW_UPSTREAM_PORT &&
+	    dev->pcie_type != PCIE_SW_DOWNSTREAM_PORT)
+		return;
+
+	if (enable)
+		pci_enable_pcie_error_reporting(dev);
+	else
+		pci_disable_pcie_error_reporting(dev);
+}
+
+/**
+ * set_downstream_devices_error_reporting - enable/disable the error reporting  bits on the root port and its downstream ports.
+ * @dev: pointer to root port's pci_dev data structure
+ * @enable: true = enable error reporting, false = disable error reporting.
+ */
+static void set_downstream_devices_error_reporting(struct pci_dev *dev,
+						   bool enable)
+{
+	set_device_error_reporting(dev, &enable);
+	pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
+}
+
 static int find_device_iter(struct device *device, void *data)
 {
 	struct pci_dev *dev;
@@ -525,15 +553,11 @@
 	pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
 	pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
 
-	/* Enable Root Port device reporting error itself */
-	pci_read_config_word(pdev, pos+PCI_EXP_DEVCTL, &reg16);
-	reg16 = reg16 |
-		PCI_EXP_DEVCTL_CERE |
-		PCI_EXP_DEVCTL_NFERE |
-		PCI_EXP_DEVCTL_FERE |
-		PCI_EXP_DEVCTL_URRE;
-	pci_write_config_word(pdev, pos+PCI_EXP_DEVCTL,
-		reg16);
+	/*
+	 * Enable error reporting for the root port device and downstream port
+	 * devices.
+	 */
+	set_downstream_devices_error_reporting(pdev, true);
 
 	/* Enable Root Port's interrupt in response to error messages */
 	pci_write_config_dword(pdev,
@@ -553,6 +577,12 @@
 	u32 reg32;
 	int pos;
 
+	/*
+	 * Disable error reporting for the root port device and downstream port
+	 * devices.
+	 */
+	set_downstream_devices_error_reporting(pdev, false);
+
 	pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
 	/* Disable Root's interrupt in response to error messages */
 	pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0);
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index f9b874e..248b4db 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -97,8 +97,6 @@
 
 	pcie_portdrv_save_config(dev);
 
-	pci_enable_pcie_error_reporting(dev);
-
 	return 0;
 }
 
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index baad093..f20d553 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1584,6 +1584,7 @@
  */
 #define AMD_813X_MISC			0x40
 #define AMD_813X_NOIOAMODE		(1<<0)
+#define AMD_813X_REV_B2			0x13
 
 static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
 {
@@ -1591,6 +1592,8 @@
 
 	if (noioapicquirk)
 		return;
+	if (dev->revision == AMD_813X_REV_B2)
+		return;
 
 	pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword);
 	pci_config_dword &= ~AMD_813X_NOIOAMODE;
@@ -1981,7 +1984,6 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
 			quirk_msi_ht_cap);
 
-
 /* The nVidia CK804 chipset may have 2 HT MSI mappings.
  * MSI are supported if the MSI capability set in any of these mappings.
  */
@@ -2032,6 +2034,9 @@
 			 PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
 			 ht_enable_msi_mapping);
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
+			 ht_enable_msi_mapping);
+
 /* The P5N32-SLI Premium motherboard from Asus has a problem with msi
  * for the MCP55 NIC. It is not yet determined whether the msi problem
  * also affects other devices. As for now, turn off msi for this device.
@@ -2048,10 +2053,100 @@
 			PCI_DEVICE_ID_NVIDIA_NVENET_15,
 			nvenet_msi_disable);
 
+static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
+{
+	struct pci_dev *host_bridge;
+	int pos;
+	int i, dev_no;
+	int found = 0;
+
+	dev_no = dev->devfn >> 3;
+	for (i = dev_no; i >= 0; i--) {
+		host_bridge = pci_get_slot(dev->bus, PCI_DEVFN(i, 0));
+		if (!host_bridge)
+			continue;
+
+		pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE);
+		if (pos != 0) {
+			found = 1;
+			break;
+		}
+		pci_dev_put(host_bridge);
+	}
+
+	if (!found)
+		return;
+
+	/* root did that ! */
+	if (msi_ht_cap_enabled(host_bridge))
+		goto out;
+
+	ht_enable_msi_mapping(dev);
+
+out:
+	pci_dev_put(host_bridge);
+}
+
+static void __devinit ht_disable_msi_mapping(struct pci_dev *dev)
+{
+	int pos, ttl = 48;
+
+	pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
+	while (pos && ttl--) {
+		u8 flags;
+
+		if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
+					 &flags) == 0) {
+			dev_info(&dev->dev, "Enabling HT MSI Mapping\n");
+
+			pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
+					      flags & ~HT_MSI_FLAGS_ENABLE);
+		}
+		pos = pci_find_next_ht_capability(dev, pos,
+						  HT_CAPTYPE_MSI_MAPPING);
+	}
+}
+
+static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
+{
+	int pos, ttl = 48;
+	int found = 0;
+
+	/* check if there is HT MSI cap or enabled on this device */
+	pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
+	while (pos && ttl--) {
+		u8 flags;
+
+		if (found < 1)
+			found = 1;
+		if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
+					 &flags) == 0) {
+			if (flags & HT_MSI_FLAGS_ENABLE) {
+				if (found < 2) {
+					found = 2;
+					break;
+				}
+			}
+		}
+		pos = pci_find_next_ht_capability(dev, pos,
+						  HT_CAPTYPE_MSI_MAPPING);
+	}
+
+	return found;
+}
+
 static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
 {
 	struct pci_dev *host_bridge;
-	int pos, ttl = 48;
+	int pos;
+	int found;
+
+	/* check if there is HT MSI cap or enabled on this device */
+	found = ht_check_msi_mapping(dev);
+
+	/* no HT MSI CAP */
+	if (found == 0)
+		return;
 
 	/*
 	 * HT MSI mapping should be disabled on devices that are below
@@ -2067,24 +2162,19 @@
 	pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE);
 	if (pos != 0) {
 		/* Host bridge is to HT */
-		ht_enable_msi_mapping(dev);
+		if (found == 1) {
+			/* it is not enabled, try to enable it */
+			nv_ht_enable_msi_mapping(dev);
+		}
 		return;
 	}
 
-	/* Host bridge is not to HT, disable HT MSI mapping on this device */
-	pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
-	while (pos && ttl--) {
-		u8 flags;
+	/* HT MSI is not enabled */
+	if (found == 1)
+		return;
 
-		if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
-					 &flags) == 0) {
-			dev_info(&dev->dev, "Disabling HT MSI mapping");
-			pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
-					      flags & ~HT_MSI_FLAGS_ENABLE);
-		}
-		pos = pci_find_next_ht_capability(dev, pos,
-						  HT_CAPTYPE_MSI_MAPPING);
-	}
+	/* Host bridge is not to HT, disable HT MSI mapping on this device */
+	ht_disable_msi_mapping(dev);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk);
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 3599828..022e89f 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -133,7 +133,7 @@
 # define SCSPTR3	0xffed0024	/* 16 bit SCIF */
 # define SCSPTR4	0xffee0024	/* 16 bit SCIF */
 # define SCSPTR5	0xffef0024	/* 16 bit SCIF */
-# define SCIF_OPER	0x0001		/* Overrun error bit */
+# define SCIF_ORER	0x0001		/* Overrun error bit */
 # define SCSCR_INIT(port)	0x3a	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
       defined(CONFIG_CPU_SUBTYPE_SH7203) || \
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index ab69c1b..c2747bc 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -2164,19 +2164,20 @@
 	if (scan_timer.function != NULL)
 		del_timer(&scan_timer);
 
-	if (keypad_enabled)
-		misc_deregister(&keypad_dev);
+	if (pprt != NULL) {
+		if (keypad_enabled)
+			misc_deregister(&keypad_dev);
 
-	if (lcd_enabled) {
-		panel_lcd_print("\x0cLCD driver " PANEL_VERSION
-				"\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
-		misc_deregister(&lcd_dev);
+		if (lcd_enabled) {
+			panel_lcd_print("\x0cLCD driver " PANEL_VERSION
+					"\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
+			misc_deregister(&lcd_dev);
+		}
+
+		/* TODO: free all input signals */
+		parport_release(pprt);
+		parport_unregister_device(pprt);
 	}
-
-	/* TODO: free all input signals */
-
-	parport_release(pprt);
-	parport_unregister_device(pprt);
 	parport_unregister_driver(&panel_driver);
 }
 
diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig
index 79c225a..f636296 100644
--- a/drivers/staging/rtl8187se/Kconfig
+++ b/drivers/staging/rtl8187se/Kconfig
@@ -1,5 +1,6 @@
 config RTL8187SE
 	tristate "RealTek RTL8187SE Wireless LAN NIC driver"
 	depends on PCI
+	depends on WIRELESS_EXT && COMPAT_NET_DEV_OPS
 	default N
 	---help---
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
index af64cfb..7370296 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
@@ -234,20 +234,21 @@
 void ieee80211_crypto_deinit(void)
 {
 	struct list_head *ptr, *n;
+	struct ieee80211_crypto_alg *alg = NULL;
 
 	if (hcrypt == NULL)
 		return;
 
-	for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
-	     ptr = n, n = ptr->next) {
-		struct ieee80211_crypto_alg *alg =
-			(struct ieee80211_crypto_alg *) ptr;
-		list_del(ptr);
-		printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
-		       "'%s' (deinit)\n", alg->ops->name);
-		kfree(alg);
+	list_for_each_safe(ptr, n, &hcrypt->algs) {
+		alg = list_entry(ptr, struct ieee80211_crypto_alg, list);
+		if (alg) {
+			list_del(ptr);
+			printk(KERN_DEBUG
+			       "ieee80211_crypt: unregistered algorithm '%s' (deinit)\n",
+			       alg->ops->name);
+			kfree(alg);
+		}
 	}
-
 	kfree(hcrypt);
 }
 
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 9453495..66de5cc 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -6161,10 +6161,10 @@
 {
 	pci_unregister_driver (&rtl8180_pci_driver);
 	rtl8180_proc_module_remove();
-	ieee80211_crypto_deinit();
 	ieee80211_crypto_tkip_exit();
 	ieee80211_crypto_ccmp_exit();
 	ieee80211_crypto_wep_exit();
+	ieee80211_crypto_deinit();
 	DMESG("Exiting");
 }
 
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index b003f9a..f716b2e 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -319,16 +319,18 @@
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct wbsoft_priv *priv;
 	struct ieee80211_hw *dev;
-	int err;
+	int nr, err;
 
 	usb_get_dev(udev);
 
 	// 20060630.2 Check the device if it already be opened
-	err = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ),
-			      0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
-			      0x0, 0x400, &ltmp, 4, HZ*100 );
-	if (err)
+	nr = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ),
+			     0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
+			     0x0, 0x400, &ltmp, 4, HZ*100 );
+	if (nr < 0) {
+		err = nr;
 		goto error;
+	}
 
 	ltmp = cpu_to_le32(ltmp);
 	if (ltmp) {  // Is already initialized?
@@ -337,8 +339,10 @@
 	}
 
 	dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
-	if (!dev)
+	if (!dev) {
+		err = -ENOMEM;
 		goto error;
+	}
 
 	priv = dev->priv;
 
@@ -369,9 +373,11 @@
 	}
 
 	dev->extra_tx_headroom = 12;	/* FIXME */
-	dev->flags = 0;
+	dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
+	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 
 	dev->channel_change_time = 1000;
+	dev->max_signal = 100;
 	dev->queues = 1;
 
 	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &wbsoft_band_2GHz;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 326dd7f..b3d5a23 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1376,6 +1376,15 @@
 	{ USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
+	{ USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
+	},
+	{ USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */
+	.driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on
+					   data interface instead of
+					   communications interface.
+					   Maybe we should define a new
+					   quirk for this. */
+	},
 
 	/* control interfaces with various AT-command sets */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 31fb204..49e7f56 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -653,7 +653,7 @@
 		if (result <= 0 && result != -ETIMEDOUT)
 			continue;
 		if (result > 1 && ((u8 *)buf)[1] != type) {
-			result = -EPROTO;
+			result = -ENODATA;
 			continue;
 		}
 		break;
@@ -696,8 +696,13 @@
 			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 			(USB_DT_STRING << 8) + index, langid, buf, size,
 			USB_CTRL_GET_TIMEOUT);
-		if (!(result == 0 || result == -EPIPE))
-			break;
+		if (result == 0 || result == -EPIPE)
+			continue;
+		if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
+			result = -ENODATA;
+			continue;
+		}
+		break;
 	}
 	return result;
 }
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 3219d13..e55fef5 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -191,6 +191,7 @@
 	boolean "OMAP USB Device Controller"
 	depends on ARCH_OMAP
 	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
+	select USB_OTG_UTILS if ARCH_OMAP
 	help
 	   Many Texas Instruments OMAP processors have flexible full
 	   speed USB device controllers, with support for up to 30
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index 80c2e7e..38aa896 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -366,9 +366,9 @@
 		f->hs_descriptors = usb_copy_descriptors(hs_function);
 
 		obex->hs.obex_in = usb_find_endpoint(hs_function,
-				f->descriptors, &obex_hs_ep_in_desc);
+				f->hs_descriptors, &obex_hs_ep_in_desc);
 		obex->hs.obex_out = usb_find_endpoint(hs_function,
-				f->descriptors, &obex_hs_ep_out_desc);
+				f->hs_descriptors, &obex_hs_ep_out_desc);
 	}
 
 	/* Avoid letting this gadget enumerate until the userspace
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index b10fa31..1ab9dac 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -3879,7 +3879,11 @@
 	mod_data.protocol_type = USB_SC_SCSI;
 	mod_data.protocol_name = "Transparent SCSI";
 
-	if (gadget_is_sh(fsg->gadget))
+	/* Some peripheral controllers are known not to be able to
+	 * halt bulk endpoints correctly.  If one of them is present,
+	 * disable stalls.
+	 */
+	if (gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget))
 		mod_data.can_stall = 0;
 
 	if (mod_data.release == 0xffff) {	// Parameter wasn't set
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index f3c6703..d8d9a52 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -404,7 +404,10 @@
 	}
 	if (zlt)
 		tmp |= EP_QUEUE_HEAD_ZLT_SEL;
+
 	p_QH->max_pkt_length = cpu_to_le32(tmp);
+	p_QH->next_dtd_ptr = 1;
+	p_QH->size_ioc_int_sts = 0;
 
 	return;
 }
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 4725d15..e551bb3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -485,6 +485,7 @@
 	 * periodic_size can shrink by USBCMD update if hcc_params allows.
 	 */
 	ehci->periodic_size = DEFAULT_I_TDPS;
+	INIT_LIST_HEAD(&ehci->cached_itd_list);
 	if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
 		return retval;
 
@@ -497,6 +498,7 @@
 
 	ehci->reclaim = NULL;
 	ehci->next_uframe = -1;
+	ehci->clock_frame = -1;
 
 	/*
 	 * dedicate a qh for the async ring head, since we couldn't unlink
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 0431397..10d5291 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -128,6 +128,7 @@
 
 static void ehci_mem_cleanup (struct ehci_hcd *ehci)
 {
+	free_cached_itd_list(ehci);
 	if (ehci->async)
 		qh_put (ehci->async);
 	ehci->async = NULL;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index a081ee6..07bcb93 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1004,7 +1004,8 @@
 
 		is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
 		stream->bEndpointAddress &= 0x0f;
-		stream->ep->hcpriv = NULL;
+		if (stream->ep)
+			stream->ep->hcpriv = NULL;
 
 		if (stream->rescheduled) {
 			ehci_info (ehci, "ep%d%s-iso rescheduled "
@@ -1653,14 +1654,28 @@
 			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
 	}
 	iso_stream_put (ehci, stream);
-	/* OK to recycle this ITD now that its completion callback ran. */
+
 done:
 	usb_put_urb(urb);
 	itd->urb = NULL;
-	itd->stream = NULL;
-	list_move(&itd->itd_list, &stream->free_list);
-	iso_stream_put(ehci, stream);
-
+	if (ehci->clock_frame != itd->frame || itd->index[7] != -1) {
+		/* OK to recycle this ITD now. */
+		itd->stream = NULL;
+		list_move(&itd->itd_list, &stream->free_list);
+		iso_stream_put(ehci, stream);
+	} else {
+		/* HW might remember this ITD, so we can't recycle it yet.
+		 * Move it to a safe place until a new frame starts.
+		 */
+		list_move(&itd->itd_list, &ehci->cached_itd_list);
+		if (stream->refcount == 2) {
+			/* If iso_stream_put() were called here, stream
+			 * would be freed.  Instead, just prevent reuse.
+			 */
+			stream->ep->hcpriv = NULL;
+			stream->ep = NULL;
+		}
+	}
 	return retval;
 }
 
@@ -2101,6 +2116,20 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void free_cached_itd_list(struct ehci_hcd *ehci)
+{
+	struct ehci_itd *itd, *n;
+
+	list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
+		struct ehci_iso_stream	*stream = itd->stream;
+		itd->stream = NULL;
+		list_move(&itd->itd_list, &stream->free_list);
+		iso_stream_put(ehci, stream);
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
 static void
 scan_periodic (struct ehci_hcd *ehci)
 {
@@ -2115,10 +2144,17 @@
 	 * Touches as few pages as possible:  cache-friendly.
 	 */
 	now_uframe = ehci->next_uframe;
-	if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
+	if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
 		clock = ehci_readl(ehci, &ehci->regs->frame_index);
-	else
+		clock_frame = (clock >> 3) % ehci->periodic_size;
+	} else  {
 		clock = now_uframe + mod - 1;
+		clock_frame = -1;
+	}
+	if (ehci->clock_frame != clock_frame) {
+		free_cached_itd_list(ehci);
+		ehci->clock_frame = clock_frame;
+	}
 	clock %= mod;
 	clock_frame = clock >> 3;
 
@@ -2277,6 +2313,10 @@
 			/* rescan the rest of this frame, then ... */
 			clock = now;
 			clock_frame = clock >> 3;
+			if (ehci->clock_frame != clock_frame) {
+				free_cached_itd_list(ehci);
+				ehci->clock_frame = clock_frame;
+			}
 		} else {
 			now_uframe++;
 			now_uframe %= mod;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index fb7054cc..262b00c 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -87,6 +87,10 @@
 	int			next_uframe;	/* scan periodic, start here */
 	unsigned		periodic_sched;	/* periodic activity count */
 
+	/* list of itds completed while clock_frame was still active */
+	struct list_head	cached_itd_list;
+	unsigned		clock_frame;
+
 	/* per root hub port */
 	unsigned long		reset_done [EHCI_MAX_ROOT_PORTS];
 
@@ -220,6 +224,8 @@
 	}
 }
 
+static void free_cached_itd_list(struct ehci_hcd *ehci);
+
 /*-------------------------------------------------------------------------*/
 
 #include <linux/usb/ehci_def.h>
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 5a8fd5d..2dc7606 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -377,18 +377,8 @@
 	u32		revision;
 
 	musb->mregs += DAVINCI_BASE_OFFSET;
-#if 0
-	/* REVISIT there's something odd about clocking, this
-	 * didn't appear do the job ...
-	 */
-	musb->clock = clk_get(pDevice, "usb");
-	if (IS_ERR(musb->clock))
-		return PTR_ERR(musb->clock);
 
-	status = clk_enable(musb->clock);
-	if (status < 0)
-		return -ENODEV;
-#endif
+	clk_enable(musb->clock);
 
 	/* returns zero if e.g. not clocked */
 	revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
@@ -453,5 +443,8 @@
 	}
 
 	phy_off();
+
+	clk_disable(musb->clock);
+
 	return 0;
 }
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 2cc34fa..af77e46 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -115,7 +115,7 @@
 
 
 unsigned musb_debug;
-module_param(musb_debug, uint, S_IRUGO | S_IWUSR);
+module_param_named(debug, musb_debug, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
 
 #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
@@ -767,6 +767,7 @@
 #ifdef CONFIG_USB_MUSB_HDRC_HCD
 		case OTG_STATE_A_HOST:
 		case OTG_STATE_A_SUSPEND:
+			usb_hcd_resume_root_hub(musb_to_hcd(musb));
 			musb_root_disconnect(musb);
 			if (musb->a_wait_bcon != 0)
 				musb_platform_try_idle(musb, jiffies
@@ -1815,7 +1816,7 @@
 #ifdef CONFIG_SYSFS
 	device_remove_file(musb->controller, &dev_attr_mode);
 	device_remove_file(musb->controller, &dev_attr_vbus);
-#ifdef CONFIG_USB_MUSB_OTG
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	device_remove_file(musb->controller, &dev_attr_srp);
 #endif
 #endif
@@ -2063,7 +2064,7 @@
 #ifdef CONFIG_SYSFS
 	device_remove_file(musb->controller, &dev_attr_mode);
 	device_remove_file(musb->controller, &dev_attr_vbus);
-#ifdef CONFIG_USB_MUSB_OTG
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	device_remove_file(musb->controller, &dev_attr_srp);
 #endif
 #endif
@@ -2243,10 +2244,10 @@
 	return platform_driver_probe(&musb_driver, musb_probe);
 }
 
-/* make us init after usbcore and before usb
- * gadget and host-side drivers start to register
+/* make us init after usbcore and i2c (transceivers, regulators, etc)
+ * and before usb gadget and host-side drivers start to register
  */
-subsys_initcall(musb_init);
+fs_initcall(musb_init);
 
 static void __exit musb_cleanup(void)
 {
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 4ea3053..c7ebd08 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -575,7 +575,7 @@
 	struct usb_request	*request = &req->request;
 	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_out;
 	void __iomem		*epio = musb->endpoints[epnum].regs;
-	u16			fifo_count = 0;
+	unsigned		fifo_count = 0;
 	u16			len = musb_ep->packet_sz;
 
 	csr = musb_readw(epio, MUSB_RXCSR);
@@ -687,7 +687,7 @@
 					len, fifo_count,
 					musb_ep->packet_sz);
 
-			fifo_count = min(len, fifo_count);
+			fifo_count = min_t(unsigned, len, fifo_count);
 
 #ifdef	CONFIG_USB_TUSB_OMAP_DMA
 			if (tusb_dma_omap() && musb_ep->dma) {
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index a035cec..6dbbd07 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -335,16 +335,11 @@
 static struct musb_qh *
 musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
 {
-	int			is_in;
 	struct musb_hw_ep	*ep = qh->hw_ep;
 	struct musb		*musb = ep->musb;
+	int			is_in = usb_pipein(urb->pipe);
 	int			ready = qh->is_ready;
 
-	if (ep->is_shared_fifo)
-		is_in = 1;
-	else
-		is_in = usb_pipein(urb->pipe);
-
 	/* save toggle eagerly, for paranoia */
 	switch (qh->type) {
 	case USB_ENDPOINT_XFER_BULK:
@@ -432,7 +427,7 @@
 	else
 		qh = musb_giveback(qh, urb, urb->status);
 
-	if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) {
+	if (qh != NULL && qh->is_ready) {
 		DBG(4, "... next ep%d %cX urb %p\n",
 				hw_ep->epnum, is_in ? 'R' : 'T',
 				next_urb(qh));
@@ -942,8 +937,8 @@
 	switch (musb->ep0_stage) {
 	case MUSB_EP0_IN:
 		fifo_dest = urb->transfer_buffer + urb->actual_length;
-		fifo_count = min(len, ((u16) (urb->transfer_buffer_length
-					- urb->actual_length)));
+		fifo_count = min_t(size_t, len, urb->transfer_buffer_length -
+				   urb->actual_length);
 		if (fifo_count < len)
 			urb->status = -EOVERFLOW;
 
@@ -976,10 +971,9 @@
 		}
 		/* FALLTHROUGH */
 	case MUSB_EP0_OUT:
-		fifo_count = min(qh->maxpacket, ((u16)
-				(urb->transfer_buffer_length
-				- urb->actual_length)));
-
+		fifo_count = min_t(size_t, qh->maxpacket,
+				   urb->transfer_buffer_length -
+				   urb->actual_length);
 		if (fifo_count) {
 			fifo_dest = (u8 *) (urb->transfer_buffer
 					+ urb->actual_length);
@@ -1161,7 +1155,8 @@
 	struct urb		*urb;
 	struct musb_hw_ep	*hw_ep = musb->endpoints + epnum;
 	void __iomem		*epio = hw_ep->regs;
-	struct musb_qh		*qh = hw_ep->out_qh;
+	struct musb_qh		*qh = hw_ep->is_shared_fifo ? hw_ep->in_qh
+							    : hw_ep->out_qh;
 	u32			status = 0;
 	void __iomem		*mbase = musb->mregs;
 	struct dma_channel	*dma;
@@ -1308,7 +1303,8 @@
 		 * packets before updating TXCSR ... other docs disagree ...
 		 */
 		/* PIO:  start next packet in this URB */
-		wLength = min(qh->maxpacket, (u16) wLength);
+		if (wLength > qh->maxpacket)
+			wLength = qh->maxpacket;
 		musb_write_fifo(hw_ep, wLength, buf);
 		qh->segsize = wLength;
 
@@ -1867,19 +1863,21 @@
 	}
 	qh->type_reg = type_reg;
 
-	/* precompute rxinterval/txinterval register */
-	interval = min((u8)16, epd->bInterval);	/* log encoding */
+	/* Precompute RXINTERVAL/TXINTERVAL register */
 	switch (qh->type) {
 	case USB_ENDPOINT_XFER_INT:
-		/* fullspeed uses linear encoding */
-		if (USB_SPEED_FULL == urb->dev->speed) {
-			interval = epd->bInterval;
-			if (!interval)
-				interval = 1;
+		/*
+		 * Full/low speeds use the  linear encoding,
+		 * high speed uses the logarithmic encoding.
+		 */
+		if (urb->dev->speed <= USB_SPEED_FULL) {
+			interval = max_t(u8, epd->bInterval, 1);
+			break;
 		}
 		/* FALLTHROUGH */
 	case USB_ENDPOINT_XFER_ISOC:
-		/* iso always uses log encoding */
+		/* ISO always uses logarithmic encoding */
+		interval = min_t(u8, epd->bInterval, 16);
 		break;
 	default:
 		/* REVISIT we actually want to use NAK limits, hinting to the
@@ -2037,9 +2035,9 @@
 		goto done;
 
 	/* Any URB not actively programmed into endpoint hardware can be
-	 * immediately given back.  Such an URB must be at the head of its
+	 * immediately given back; that's any URB not at the head of an
 	 * endpoint queue, unless someday we get real DMA queues.  And even
-	 * then, it might not be known to the hardware...
+	 * if it's at the head, it might not be known to the hardware...
 	 *
 	 * Otherwise abort current transfer, pending dma, etc.; urb->status
 	 * has already been updated.  This is a synchronous abort; it'd be
@@ -2078,6 +2076,15 @@
 		qh->is_ready = 0;
 		__musb_giveback(musb, urb, 0);
 		qh->is_ready = ready;
+
+		/* If nothing else (usually musb_giveback) is using it
+		 * and its URB list has emptied, recycle this qh.
+		 */
+		if (ready && list_empty(&qh->hep->urb_list)) {
+			qh->hep->hcpriv = NULL;
+			list_del(&qh->ring);
+			kfree(qh);
+		}
 	} else
 		ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
 done:
@@ -2093,15 +2100,16 @@
 	unsigned long		flags;
 	struct musb		*musb = hcd_to_musb(hcd);
 	u8			is_in = epnum & USB_DIR_IN;
-	struct musb_qh		*qh = hep->hcpriv;
-	struct urb		*urb, *tmp;
+	struct musb_qh		*qh;
+	struct urb		*urb;
 	struct list_head	*sched;
 
-	if (!qh)
-		return;
-
 	spin_lock_irqsave(&musb->lock, flags);
 
+	qh = hep->hcpriv;
+	if (qh == NULL)
+		goto exit;
+
 	switch (qh->type) {
 	case USB_ENDPOINT_XFER_CONTROL:
 		sched = &musb->control;
@@ -2135,13 +2143,28 @@
 
 		/* cleanup */
 		musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
-	} else
-		urb = NULL;
 
-	/* then just nuke all the others */
-	list_for_each_entry_safe_from(urb, tmp, &hep->urb_list, urb_list)
-		musb_giveback(qh, urb, -ESHUTDOWN);
+		/* Then nuke all the others ... and advance the
+		 * queue on hw_ep (e.g. bulk ring) when we're done.
+		 */
+		while (!list_empty(&hep->urb_list)) {
+			urb = next_urb(qh);
+			urb->status = -ESHUTDOWN;
+			musb_advance_schedule(musb, urb, qh->hw_ep, is_in);
+		}
+	} else {
+		/* Just empty the queue; the hardware is busy with
+		 * other transfers, and since !qh->is_ready nothing
+		 * will activate any of these as it advances.
+		 */
+		while (!list_empty(&hep->urb_list))
+			__musb_giveback(musb, next_urb(qh), -ESHUTDOWN);
 
+		hep->hcpriv = NULL;
+		list_del(&qh->ring);
+		kfree(qh);
+	}
+exit:
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index bfd0b68..b7c132b 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -294,7 +294,11 @@
 
 /* Ericsson products */
 #define ERICSSON_VENDOR_ID			0x0bdb
-#define ERICSSON_PRODUCT_F3507G			0x1900
+#define ERICSSON_PRODUCT_F3507G_1		0x1900
+#define ERICSSON_PRODUCT_F3507G_2		0x1902
+
+#define BENQ_VENDOR_ID				0x04a5
+#define BENQ_PRODUCT_H10			0x4068
 
 static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
@@ -509,7 +513,10 @@
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
 	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
-	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G) },
+	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) },
+	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) },
+	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
+	{ USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 50dc33a..6f59c8e 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -907,13 +907,13 @@
 		"Genesys Logic",
 		"USB to IDE Optical",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
+		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
 		"Genesys Logic",
 		"USB to IDE Disk",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
+		US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Ben Efros <ben@pc-doctor.com> */
 UNUSUAL_DEV(  0x05e3, 0x0723, 0x9451, 0x9451,
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 8d0b1fb..1f51366 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -16,6 +16,12 @@
 	  Say Y here if you want to connect 1-wire
 	  simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
 
+config W1_SLAVE_DS2431
+	tristate "1kb EEPROM family support (DS2431)"
+	help
+	  Say Y here if you want to use a 1-wire
+	  1kb EEPROM family device (DS2431)
+
 config W1_SLAVE_DS2433
 	tristate "4kb EEPROM family support (DS2433)"
 	help
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index 990f400..f1f51f1 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_W1_SLAVE_THERM)	+= w1_therm.o
 obj-$(CONFIG_W1_SLAVE_SMEM)	+= w1_smem.o
+obj-$(CONFIG_W1_SLAVE_DS2431)	+= w1_ds2431.o
 obj-$(CONFIG_W1_SLAVE_DS2433)	+= w1_ds2433.o
 obj-$(CONFIG_W1_SLAVE_DS2760)	+= w1_ds2760.o
 obj-$(CONFIG_W1_SLAVE_BQ27000)	+= w1_bq27000.o
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c
index 858c16a..1394471 100644
--- a/drivers/w1/slaves/w1_ds2433.c
+++ b/drivers/w1/slaves/w1_ds2433.c
@@ -156,6 +156,9 @@
  */
 static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
 {
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
+	struct w1_f23_data *f23 = sl->family_data;
+#endif
 	u8 wrbuf[4];
 	u8 rdbuf[W1_PAGE_SIZE + 3];
 	u8 es = (addr + len - 1) & 0x1f;
@@ -196,7 +199,9 @@
 
 	/* Reset the bus to wake up the EEPROM (this may not be needed) */
 	w1_reset_bus(sl->master);
-
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
+	f23->validcrc &= ~(1 << (addr >> W1_PAGE_BITS));
+#endif
 	return 0;
 }
 
diff --git a/fs/bio.c b/fs/bio.c
index 72ab251..124b95c 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -302,7 +302,7 @@
 struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
 {
 	struct bio *bio = NULL;
-	void *p;
+	void *uninitialized_var(p);
 
 	if (bs) {
 		p = mempool_alloc(bs->bio_pool, gfp_mask);
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index a8c9693..72677ce 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -66,6 +66,9 @@
 	 */
 	struct list_head delalloc_inodes;
 
+	/* the space_info for where this inode's data allocations are done */
+	struct btrfs_space_info *space_info;
+
 	/* full 64 bit generation number, struct vfs_inode doesn't have a big
 	 * enough field for this.
 	 */
@@ -94,6 +97,11 @@
 	 */
 	u64 delalloc_bytes;
 
+	/* total number of bytes that may be used for this inode for
+	 * delalloc
+	 */
+	u64 reserved_bytes;
+
 	/*
 	 * the size of the file stored in the metadata on disk.  data=ordered
 	 * means the in-memory i_size might be larger than the size on disk
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 766b31a..82491ba 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -596,13 +596,27 @@
 
 struct btrfs_space_info {
 	u64 flags;
-	u64 total_bytes;
-	u64 bytes_used;
-	u64 bytes_pinned;
-	u64 bytes_reserved;
-	u64 bytes_readonly;
-	int full;
-	int force_alloc;
+
+	u64 total_bytes;	/* total bytes in the space */
+	u64 bytes_used;		/* total bytes used on disk */
+	u64 bytes_pinned;	/* total bytes pinned, will be freed when the
+				   transaction finishes */
+	u64 bytes_reserved;	/* total bytes the allocator has reserved for
+				   current allocations */
+	u64 bytes_readonly;	/* total bytes that are read only */
+
+	/* delalloc accounting */
+	u64 bytes_delalloc;	/* number of bytes reserved for allocation,
+				   this space is not necessarily reserved yet
+				   by the allocator */
+	u64 bytes_may_use;	/* number of bytes that may be used for
+				   delalloc */
+
+	int full;		/* indicates that we cannot allocate any more
+				   chunks for this space */
+	int force_alloc;	/* set if we need to force a chunk alloc for
+				   this space */
+
 	struct list_head list;
 
 	/* for block groups in our same type */
@@ -1782,6 +1796,16 @@
 int btrfs_cleanup_reloc_trees(struct btrfs_root *root);
 int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len);
 u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags);
+void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde);
+int btrfs_check_metadata_free_space(struct btrfs_root *root);
+int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,
+				u64 bytes);
+void btrfs_free_reserved_data_space(struct btrfs_root *root,
+				    struct inode *inode, u64 bytes);
+void btrfs_delalloc_reserve_space(struct btrfs_root *root, struct inode *inode,
+				 u64 bytes);
+void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode,
+			      u64 bytes);
 /* ctree.c */
 int btrfs_previous_item(struct btrfs_root *root,
 			struct btrfs_path *path, u64 min_objectid,
@@ -2027,8 +2051,6 @@
 unsigned long btrfs_force_ra(struct address_space *mapping,
 			      struct file_ra_state *ra, struct file *file,
 			      pgoff_t offset, pgoff_t last_index);
-int btrfs_check_free_space(struct btrfs_root *root, u64 num_required,
-			   int for_del);
 int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page);
 int btrfs_readpage(struct file *file, struct page *page);
 void btrfs_delete_inode(struct inode *inode);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 0a5d796..6b5966a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -60,6 +60,10 @@
 			      u64 bytenr, u64 num_bytes, int alloc,
 			      int mark_free);
 
+static int do_chunk_alloc(struct btrfs_trans_handle *trans,
+			  struct btrfs_root *extent_root, u64 alloc_bytes,
+			  u64 flags, int force);
+
 static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits)
 {
 	return (cache->flags & bits) == bits;
@@ -1909,6 +1913,7 @@
 	found->bytes_pinned = 0;
 	found->bytes_reserved = 0;
 	found->bytes_readonly = 0;
+	found->bytes_delalloc = 0;
 	found->full = 0;
 	found->force_alloc = 0;
 	*space_info = found;
@@ -1972,6 +1977,233 @@
 	return flags;
 }
 
+static u64 btrfs_get_alloc_profile(struct btrfs_root *root, u64 data)
+{
+	struct btrfs_fs_info *info = root->fs_info;
+	u64 alloc_profile;
+
+	if (data) {
+		alloc_profile = info->avail_data_alloc_bits &
+			info->data_alloc_profile;
+		data = BTRFS_BLOCK_GROUP_DATA | alloc_profile;
+	} else if (root == root->fs_info->chunk_root) {
+		alloc_profile = info->avail_system_alloc_bits &
+			info->system_alloc_profile;
+		data = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile;
+	} else {
+		alloc_profile = info->avail_metadata_alloc_bits &
+			info->metadata_alloc_profile;
+		data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile;
+	}
+
+	return btrfs_reduce_alloc_profile(root, data);
+}
+
+void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *inode)
+{
+	u64 alloc_target;
+
+	alloc_target = btrfs_get_alloc_profile(root, 1);
+	BTRFS_I(inode)->space_info = __find_space_info(root->fs_info,
+						       alloc_target);
+}
+
+/*
+ * for now this just makes sure we have at least 5% of our metadata space free
+ * for use.
+ */
+int btrfs_check_metadata_free_space(struct btrfs_root *root)
+{
+	struct btrfs_fs_info *info = root->fs_info;
+	struct btrfs_space_info *meta_sinfo;
+	u64 alloc_target, thresh;
+	int committed = 0, ret;
+
+	/* get the space info for where the metadata will live */
+	alloc_target = btrfs_get_alloc_profile(root, 0);
+	meta_sinfo = __find_space_info(info, alloc_target);
+
+again:
+	spin_lock(&meta_sinfo->lock);
+	if (!meta_sinfo->full)
+		thresh = meta_sinfo->total_bytes * 80;
+	else
+		thresh = meta_sinfo->total_bytes * 95;
+
+	do_div(thresh, 100);
+
+	if (meta_sinfo->bytes_used + meta_sinfo->bytes_reserved +
+	    meta_sinfo->bytes_pinned + meta_sinfo->bytes_readonly > thresh) {
+		struct btrfs_trans_handle *trans;
+		if (!meta_sinfo->full) {
+			meta_sinfo->force_alloc = 1;
+			spin_unlock(&meta_sinfo->lock);
+
+			trans = btrfs_start_transaction(root, 1);
+			if (!trans)
+				return -ENOMEM;
+
+			ret = do_chunk_alloc(trans, root->fs_info->extent_root,
+					     2 * 1024 * 1024, alloc_target, 0);
+			btrfs_end_transaction(trans, root);
+			goto again;
+		}
+		spin_unlock(&meta_sinfo->lock);
+
+		if (!committed) {
+			committed = 1;
+			trans = btrfs_join_transaction(root, 1);
+			if (!trans)
+				return -ENOMEM;
+			ret = btrfs_commit_transaction(trans, root);
+			if (ret)
+				return ret;
+			goto again;
+		}
+		return -ENOSPC;
+	}
+	spin_unlock(&meta_sinfo->lock);
+
+	return 0;
+}
+
+/*
+ * This will check the space that the inode allocates from to make sure we have
+ * enough space for bytes.
+ */
+int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,
+				u64 bytes)
+{
+	struct btrfs_space_info *data_sinfo;
+	int ret = 0, committed = 0;
+
+	/* make sure bytes are sectorsize aligned */
+	bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1);
+
+	data_sinfo = BTRFS_I(inode)->space_info;
+again:
+	/* make sure we have enough space to handle the data first */
+	spin_lock(&data_sinfo->lock);
+	if (data_sinfo->total_bytes - data_sinfo->bytes_used -
+	    data_sinfo->bytes_delalloc - data_sinfo->bytes_reserved -
+	    data_sinfo->bytes_pinned - data_sinfo->bytes_readonly -
+	    data_sinfo->bytes_may_use < bytes) {
+		struct btrfs_trans_handle *trans;
+
+		/*
+		 * if we don't have enough free bytes in this space then we need
+		 * to alloc a new chunk.
+		 */
+		if (!data_sinfo->full) {
+			u64 alloc_target;
+
+			data_sinfo->force_alloc = 1;
+			spin_unlock(&data_sinfo->lock);
+
+			alloc_target = btrfs_get_alloc_profile(root, 1);
+			trans = btrfs_start_transaction(root, 1);
+			if (!trans)
+				return -ENOMEM;
+
+			ret = do_chunk_alloc(trans, root->fs_info->extent_root,
+					     bytes + 2 * 1024 * 1024,
+					     alloc_target, 0);
+			btrfs_end_transaction(trans, root);
+			if (ret)
+				return ret;
+			goto again;
+		}
+		spin_unlock(&data_sinfo->lock);
+
+		/* commit the current transaction and try again */
+		if (!committed) {
+			committed = 1;
+			trans = btrfs_join_transaction(root, 1);
+			if (!trans)
+				return -ENOMEM;
+			ret = btrfs_commit_transaction(trans, root);
+			if (ret)
+				return ret;
+			goto again;
+		}
+
+		printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes"
+		       ", %llu bytes_used, %llu bytes_reserved, "
+		       "%llu bytes_pinned, %llu bytes_readonly, %llu may use"
+		       "%llu total\n", bytes, data_sinfo->bytes_delalloc,
+		       data_sinfo->bytes_used, data_sinfo->bytes_reserved,
+		       data_sinfo->bytes_pinned, data_sinfo->bytes_readonly,
+		       data_sinfo->bytes_may_use, data_sinfo->total_bytes);
+		return -ENOSPC;
+	}
+	data_sinfo->bytes_may_use += bytes;
+	BTRFS_I(inode)->reserved_bytes += bytes;
+	spin_unlock(&data_sinfo->lock);
+
+	return btrfs_check_metadata_free_space(root);
+}
+
+/*
+ * if there was an error for whatever reason after calling
+ * btrfs_check_data_free_space, call this so we can cleanup the counters.
+ */
+void btrfs_free_reserved_data_space(struct btrfs_root *root,
+				    struct inode *inode, u64 bytes)
+{
+	struct btrfs_space_info *data_sinfo;
+
+	/* make sure bytes are sectorsize aligned */
+	bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1);
+
+	data_sinfo = BTRFS_I(inode)->space_info;
+	spin_lock(&data_sinfo->lock);
+	data_sinfo->bytes_may_use -= bytes;
+	BTRFS_I(inode)->reserved_bytes -= bytes;
+	spin_unlock(&data_sinfo->lock);
+}
+
+/* called when we are adding a delalloc extent to the inode's io_tree */
+void btrfs_delalloc_reserve_space(struct btrfs_root *root, struct inode *inode,
+				  u64 bytes)
+{
+	struct btrfs_space_info *data_sinfo;
+
+	/* get the space info for where this inode will be storing its data */
+	data_sinfo = BTRFS_I(inode)->space_info;
+
+	/* make sure we have enough space to handle the data first */
+	spin_lock(&data_sinfo->lock);
+	data_sinfo->bytes_delalloc += bytes;
+
+	/*
+	 * we are adding a delalloc extent without calling
+	 * btrfs_check_data_free_space first.  This happens on a weird
+	 * writepage condition, but shouldn't hurt our accounting
+	 */
+	if (unlikely(bytes > BTRFS_I(inode)->reserved_bytes)) {
+		data_sinfo->bytes_may_use -= BTRFS_I(inode)->reserved_bytes;
+		BTRFS_I(inode)->reserved_bytes = 0;
+	} else {
+		data_sinfo->bytes_may_use -= bytes;
+		BTRFS_I(inode)->reserved_bytes -= bytes;
+	}
+
+	spin_unlock(&data_sinfo->lock);
+}
+
+/* called when we are clearing an delalloc extent from the inode's io_tree */
+void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode,
+			      u64 bytes)
+{
+	struct btrfs_space_info *info;
+
+	info = BTRFS_I(inode)->space_info;
+
+	spin_lock(&info->lock);
+	info->bytes_delalloc -= bytes;
+	spin_unlock(&info->lock);
+}
+
 static int do_chunk_alloc(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *extent_root, u64 alloc_bytes,
 			  u64 flags, int force)
@@ -3105,6 +3337,10 @@
 	       (unsigned long long)(info->total_bytes - info->bytes_used -
 				    info->bytes_pinned - info->bytes_reserved),
 	       (info->full) ? "" : "not ");
+	printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu,"
+	       " may_use=%llu, used=%llu\n", info->total_bytes,
+	       info->bytes_pinned, info->bytes_delalloc, info->bytes_may_use,
+	       info->bytes_used);
 
 	down_read(&info->groups_sem);
 	list_for_each_entry(cache, &info->block_groups, list) {
@@ -3131,24 +3367,10 @@
 {
 	int ret;
 	u64 search_start = 0;
-	u64 alloc_profile;
 	struct btrfs_fs_info *info = root->fs_info;
 
-	if (data) {
-		alloc_profile = info->avail_data_alloc_bits &
-			info->data_alloc_profile;
-		data = BTRFS_BLOCK_GROUP_DATA | alloc_profile;
-	} else if (root == root->fs_info->chunk_root) {
-		alloc_profile = info->avail_system_alloc_bits &
-			info->system_alloc_profile;
-		data = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile;
-	} else {
-		alloc_profile = info->avail_metadata_alloc_bits &
-			info->metadata_alloc_profile;
-		data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile;
-	}
+	data = btrfs_get_alloc_profile(root, data);
 again:
-	data = btrfs_reduce_alloc_profile(root, data);
 	/*
 	 * the only place that sets empty_size is btrfs_realloc_node, which
 	 * is not called recursively on allocations
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 872f104..dc78954 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1091,19 +1091,24 @@
 		WARN_ON(num_pages > nrptrs);
 		memset(pages, 0, sizeof(struct page *) * nrptrs);
 
-		ret = btrfs_check_free_space(root, write_bytes, 0);
+		ret = btrfs_check_data_free_space(root, inode, write_bytes);
 		if (ret)
 			goto out;
 
 		ret = prepare_pages(root, file, pages, num_pages,
 				    pos, first_index, last_index,
 				    write_bytes);
-		if (ret)
+		if (ret) {
+			btrfs_free_reserved_data_space(root, inode,
+						       write_bytes);
 			goto out;
+		}
 
 		ret = btrfs_copy_from_user(pos, num_pages,
 					   write_bytes, pages, buf);
 		if (ret) {
+			btrfs_free_reserved_data_space(root, inode,
+						       write_bytes);
 			btrfs_drop_pages(pages, num_pages);
 			goto out;
 		}
@@ -1111,8 +1116,11 @@
 		ret = dirty_and_release_pages(NULL, root, file, pages,
 					      num_pages, pos, write_bytes);
 		btrfs_drop_pages(pages, num_pages);
-		if (ret)
+		if (ret) {
+			btrfs_free_reserved_data_space(root, inode,
+						       write_bytes);
 			goto out;
+		}
 
 		if (will_write) {
 			btrfs_fdatawrite_range(inode->i_mapping, pos,
@@ -1136,6 +1144,8 @@
 	}
 out:
 	mutex_unlock(&inode->i_mutex);
+	if (ret)
+		err = ret;
 
 out_nolock:
 	kfree(pages);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3cee77a..7d4f948 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -102,34 +102,6 @@
 }
 
 /*
- * a very lame attempt at stopping writes when the FS is 85% full.  There
- * are countless ways this is incorrect, but it is better than nothing.
- */
-int btrfs_check_free_space(struct btrfs_root *root, u64 num_required,
-			   int for_del)
-{
-	u64 total;
-	u64 used;
-	u64 thresh;
-	int ret = 0;
-
-	spin_lock(&root->fs_info->delalloc_lock);
-	total = btrfs_super_total_bytes(&root->fs_info->super_copy);
-	used = btrfs_super_bytes_used(&root->fs_info->super_copy);
-	if (for_del)
-		thresh = total * 90;
-	else
-		thresh = total * 85;
-
-	do_div(thresh, 100);
-
-	if (used + root->fs_info->delalloc_bytes + num_required > thresh)
-		ret = -ENOSPC;
-	spin_unlock(&root->fs_info->delalloc_lock);
-	return ret;
-}
-
-/*
  * this does all the hard work for inserting an inline extent into
  * the btree.  The caller should have done a btrfs_drop_extents so that
  * no overlapping inline items exist in the btree
@@ -1190,6 +1162,7 @@
 	 */
 	if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
 		struct btrfs_root *root = BTRFS_I(inode)->root;
+		btrfs_delalloc_reserve_space(root, inode, end - start + 1);
 		spin_lock(&root->fs_info->delalloc_lock);
 		BTRFS_I(inode)->delalloc_bytes += end - start + 1;
 		root->fs_info->delalloc_bytes += end - start + 1;
@@ -1223,9 +1196,12 @@
 			       (unsigned long long)end - start + 1,
 			       (unsigned long long)
 			       root->fs_info->delalloc_bytes);
+			btrfs_delalloc_free_space(root, inode, (u64)-1);
 			root->fs_info->delalloc_bytes = 0;
 			BTRFS_I(inode)->delalloc_bytes = 0;
 		} else {
+			btrfs_delalloc_free_space(root, inode,
+						  end - start + 1);
 			root->fs_info->delalloc_bytes -= end - start + 1;
 			BTRFS_I(inode)->delalloc_bytes -= end - start + 1;
 		}
@@ -2245,10 +2221,6 @@
 
 	root = BTRFS_I(dir)->root;
 
-	ret = btrfs_check_free_space(root, 1, 1);
-	if (ret)
-		goto fail;
-
 	trans = btrfs_start_transaction(root, 1);
 
 	btrfs_set_trans_block_group(trans, dir);
@@ -2261,7 +2233,6 @@
 	nr = trans->blocks_used;
 
 	btrfs_end_transaction_throttle(trans, root);
-fail:
 	btrfs_btree_balance_dirty(root, nr);
 	return ret;
 }
@@ -2284,10 +2255,6 @@
 		return -ENOTEMPTY;
 	}
 
-	ret = btrfs_check_free_space(root, 1, 1);
-	if (ret)
-		goto fail;
-
 	trans = btrfs_start_transaction(root, 1);
 	btrfs_set_trans_block_group(trans, dir);
 
@@ -2304,7 +2271,6 @@
 fail_trans:
 	nr = trans->blocks_used;
 	ret = btrfs_end_transaction_throttle(trans, root);
-fail:
 	btrfs_btree_balance_dirty(root, nr);
 
 	if (ret && !err)
@@ -2818,7 +2784,7 @@
 	if (size <= hole_start)
 		return 0;
 
-	err = btrfs_check_free_space(root, 1, 0);
+	err = btrfs_check_metadata_free_space(root);
 	if (err)
 		return err;
 
@@ -3014,6 +2980,7 @@
 	bi->last_trans = 0;
 	bi->logged_trans = 0;
 	bi->delalloc_bytes = 0;
+	bi->reserved_bytes = 0;
 	bi->disk_i_size = 0;
 	bi->flags = 0;
 	bi->index_cnt = (u64)-1;
@@ -3035,6 +3002,7 @@
 	inode->i_ino = args->ino;
 	init_btrfs_i(inode);
 	BTRFS_I(inode)->root = args->root;
+	btrfs_set_inode_space_info(args->root, inode);
 	return 0;
 }
 
@@ -3455,6 +3423,7 @@
 	BTRFS_I(inode)->index_cnt = 2;
 	BTRFS_I(inode)->root = root;
 	BTRFS_I(inode)->generation = trans->transid;
+	btrfs_set_inode_space_info(root, inode);
 
 	if (mode & S_IFDIR)
 		owner = 0;
@@ -3602,7 +3571,7 @@
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
 
-	err = btrfs_check_free_space(root, 1, 0);
+	err = btrfs_check_metadata_free_space(root);
 	if (err)
 		goto fail;
 
@@ -3665,7 +3634,7 @@
 	u64 objectid;
 	u64 index = 0;
 
-	err = btrfs_check_free_space(root, 1, 0);
+	err = btrfs_check_metadata_free_space(root);
 	if (err)
 		goto fail;
 	trans = btrfs_start_transaction(root, 1);
@@ -3733,7 +3702,7 @@
 		return -ENOENT;
 
 	btrfs_inc_nlink(inode);
-	err = btrfs_check_free_space(root, 1, 0);
+	err = btrfs_check_metadata_free_space(root);
 	if (err)
 		goto fail;
 	err = btrfs_set_inode_index(dir, &index);
@@ -3779,7 +3748,7 @@
 	u64 index = 0;
 	unsigned long nr = 1;
 
-	err = btrfs_check_free_space(root, 1, 0);
+	err = btrfs_check_metadata_free_space(root);
 	if (err)
 		goto out_unlock;
 
@@ -4336,7 +4305,7 @@
 	u64 page_start;
 	u64 page_end;
 
-	ret = btrfs_check_free_space(root, PAGE_CACHE_SIZE, 0);
+	ret = btrfs_check_data_free_space(root, inode, PAGE_CACHE_SIZE);
 	if (ret)
 		goto out;
 
@@ -4349,6 +4318,7 @@
 
 	if ((page->mapping != inode->i_mapping) ||
 	    (page_start >= size)) {
+		btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
 		/* page got truncated out from underneath us */
 		goto out_unlock;
 	}
@@ -4631,7 +4601,7 @@
 	if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
 		return -EXDEV;
 
-	ret = btrfs_check_free_space(root, 1, 0);
+	ret = btrfs_check_metadata_free_space(root);
 	if (ret)
 		goto out_unlock;
 
@@ -4749,7 +4719,7 @@
 	if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root))
 		return -ENAMETOOLONG;
 
-	err = btrfs_check_free_space(root, 1, 0);
+	err = btrfs_check_metadata_free_space(root);
 	if (err)
 		goto out_fail;
 
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 988fdc8..bca729f 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -70,7 +70,7 @@
 	u64 index = 0;
 	unsigned long nr = 1;
 
-	ret = btrfs_check_free_space(root, 1, 0);
+	ret = btrfs_check_metadata_free_space(root);
 	if (ret)
 		goto fail_commit;
 
@@ -203,7 +203,7 @@
 	if (!root->ref_cows)
 		return -EINVAL;
 
-	ret = btrfs_check_free_space(root, 1, 0);
+	ret = btrfs_check_metadata_free_space(root);
 	if (ret)
 		goto fail_unlock;
 
@@ -374,7 +374,7 @@
 	unsigned long i;
 	int ret;
 
-	ret = btrfs_check_free_space(root, inode->i_size, 0);
+	ret = btrfs_check_data_free_space(root, inode, inode->i_size);
 	if (ret)
 		return -ENOSPC;
 
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 39bd4d3..45e59d3 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1913,6 +1913,9 @@
 /* 0x00 */
 COMPATIBLE_IOCTL(FIBMAP)
 COMPATIBLE_IOCTL(FIGETBSZ)
+/* 'X' - originally XFS but some now in the VFS */
+COMPATIBLE_IOCTL(FIFREEZE)
+COMPATIBLE_IOCTL(FITHAW)
 /* RAID */
 COMPATIBLE_IOCTL(RAID_VERSION)
 COMPATIBLE_IOCTL(GET_ARRAY_INFO)
diff --git a/fs/dcache.c b/fs/dcache.c
index 937df0f..07e2d4a 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1180,7 +1180,7 @@
 	iput(inode);
 	return res;
 }
-EXPORT_SYMBOL_GPL(d_obtain_alias);
+EXPORT_SYMBOL(d_obtain_alias);
 
 /**
  * d_splice_alias - splice a disconnected dentry into the tree if one exists
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 4fb86a0..f18a919 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -715,6 +715,13 @@
 
 	if (sbi->s_log_groups_per_flex) {
 		ret2 = find_group_flex(sb, dir, &group);
+		if (ret2 == -1) {
+			ret2 = find_group_other(sb, dir, &group);
+			if (ret2 == 0 && printk_ratelimit())
+				printk(KERN_NOTICE "ext4: find_group_flex "
+				       "failed, fallback succeeded dir %lu\n",
+				       dir->i_ino);
+		}
 		goto got_group;
 	}
 
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index cbd2ca9..51cdd13 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1368,6 +1368,10 @@
 		goto out;
 	}
 
+	/* We cannot recurse into the filesystem as the transaction is already
+	 * started */
+	flags |= AOP_FLAG_NOFS;
+
 	page = grab_cache_page_write_begin(mapping, index, flags);
 	if (!page) {
 		ext4_journal_stop(handle);
@@ -1377,7 +1381,7 @@
 	*pagep = page;
 
 	ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
-							ext4_get_block);
+				ext4_get_block);
 
 	if (!ret && ext4_should_journal_data(inode)) {
 		ret = walk_page_buffers(handle, page_buffers(page),
@@ -2667,6 +2671,9 @@
 		ret = PTR_ERR(handle);
 		goto out;
 	}
+	/* We cannot recurse into the filesystem as the transaction is already
+	 * started */
+	flags |= AOP_FLAG_NOFS;
 
 	page = grab_cache_page_write_begin(mapping, index, flags);
 	if (!page) {
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 3cceef4..e958010 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -95,13 +95,17 @@
 			spin_unlock(&c->erase_completion_lock);
 			
 
-		/* This thread is purely an optimisation. But if it runs when
-		   other things could be running, it actually makes things a
-		   lot worse. Use yield() and put it at the back of the runqueue
-		   every time. Especially during boot, pulling an inode in
-		   with read_inode() is much preferable to having the GC thread
-		   get there first. */
-		yield();
+		/* Problem - immediately after bootup, the GCD spends a lot
+		 * of time in places like jffs2_kill_fragtree(); so much so
+		 * that userspace processes (like gdm and X) are starved
+		 * despite plenty of cond_resched()s and renicing.  Yield()
+		 * doesn't help, either (presumably because userspace and GCD
+		 * are generally competing for a higher latency resource -
+		 * disk).
+		 * This forces the GCD to slow the hell down.   Pulling an
+		 * inode in with read_inode() is much preferable to having
+		 * the GC thread get there first. */
+		schedule_timeout_interruptible(msecs_to_jiffies(50));
 
 		/* Put_super will send a SIGKILL and then wait on the sem.
 		 */
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 6ca08ad..1fc1e92 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -220,7 +220,7 @@
 				struct jffs2_tmp_dnode_info *tn)
 {
 	uint32_t fn_end = tn->fn->ofs + tn->fn->size;
-	struct jffs2_tmp_dnode_info *this;
+	struct jffs2_tmp_dnode_info *this, *ptn;
 
 	dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw));
 
@@ -251,11 +251,18 @@
 	if (this) {
 		/* If the node is coincident with another at a lower address,
 		   back up until the other node is found. It may be relevant */
-		while (this->overlapped)
-			this = tn_prev(this);
-
-		/* First node should never be marked overlapped */
-		BUG_ON(!this);
+		while (this->overlapped) {
+			ptn = tn_prev(this);
+			if (!ptn) {
+				/*
+				 * We killed a node which set the overlapped
+				 * flags during the scan. Fix it up.
+				 */
+				this->overlapped = 0;
+				break;
+			}
+			this = ptn;
+		}
 		dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole");
 	}
 
@@ -360,7 +367,17 @@
 			}
 			if (!this->overlapped)
 				break;
-			this = tn_prev(this);
+
+			ptn = tn_prev(this);
+			if (!ptn) {
+				/*
+				 * We killed a node which set the overlapped
+				 * flags during the scan. Fix it up.
+				 */
+				this->overlapped = 0;
+				break;
+			}
+			this = ptn;
 		}
 	}
 
@@ -456,8 +473,15 @@
 		eat_last(&rii->tn_root, &last->rb);
 		ver_insert(&ver_root, last);
 
-		if (unlikely(last->overlapped))
-			continue;
+		if (unlikely(last->overlapped)) {
+			if (pen)
+				continue;
+			/*
+			 * We killed a node which set the overlapped
+			 * flags during the scan. Fix it up.
+			 */
+			last->overlapped = 0;
+		}
 
 		/* Now we have a bunch of nodes in reverse version
 		   order, in the tree at ver_root. Most of the time,
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 60fe74035..3a9e5de 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -4796,6 +4796,29 @@
 	return ret;
 }
 
+static int ocfs2_replace_extent_rec(struct inode *inode,
+				    handle_t *handle,
+				    struct ocfs2_path *path,
+				    struct ocfs2_extent_list *el,
+				    int split_index,
+				    struct ocfs2_extent_rec *split_rec)
+{
+	int ret;
+
+	ret = ocfs2_path_bh_journal_access(handle, inode, path,
+					   path_num_items(path) - 1);
+	if (ret) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	el->l_recs[split_index] = *split_rec;
+
+	ocfs2_journal_dirty(handle, path_leaf_bh(path));
+out:
+	return ret;
+}
+
 /*
  * Mark part or all of the extent record at split_index in the leaf
  * pointed to by path as written. This removes the unwritten
@@ -4885,7 +4908,9 @@
 
 	if (ctxt.c_contig_type == CONTIG_NONE) {
 		if (ctxt.c_split_covers_rec)
-			el->l_recs[split_index] = *split_rec;
+			ret = ocfs2_replace_extent_rec(inode, handle,
+						       path, el,
+						       split_index, split_rec);
 		else
 			ret = ocfs2_split_and_insert(inode, handle, path, et,
 						     &last_eb_bh, split_index,
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 54e182a..0a28139 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -1849,12 +1849,12 @@
 		if (!mle) {
 			if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN &&
 			    res->owner != assert->node_idx) {
-				mlog(ML_ERROR, "assert_master from "
-					  "%u, but current owner is "
-					  "%u! (%.*s)\n",
-				       assert->node_idx, res->owner,
-				       namelen, name);
-				goto kill;
+				mlog(ML_ERROR, "DIE! Mastery assert from %u, "
+				     "but current owner is %u! (%.*s)\n",
+				     assert->node_idx, res->owner, namelen,
+				     name);
+				__dlm_print_one_lock_resource(res);
+				BUG();
 			}
 		} else if (mle->type != DLM_MLE_MIGRATION) {
 			if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) {
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
index d129520..4060bb3 100644
--- a/fs/ocfs2/dlm/dlmthread.c
+++ b/fs/ocfs2/dlm/dlmthread.c
@@ -181,8 +181,7 @@
 
 		spin_lock(&res->spinlock);
 		/* This ensures that clear refmap is sent after the set */
-		__dlm_wait_on_lockres_flags(res, (DLM_LOCK_RES_SETREF_INPROG |
-						  DLM_LOCK_RES_MIGRATING));
+		__dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG);
 		spin_unlock(&res->spinlock);
 
 		/* clear our bit from the master's refmap, ignore errors */
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c
index 86ca085..fcf879e 100644
--- a/fs/ocfs2/dlm/dlmunlock.c
+++ b/fs/ocfs2/dlm/dlmunlock.c
@@ -117,11 +117,11 @@
 	else
 		BUG_ON(res->owner == dlm->node_num);
 
-	spin_lock(&dlm->spinlock);
+	spin_lock(&dlm->ast_lock);
 	/* We want to be sure that we're not freeing a lock
 	 * that still has AST's pending... */
 	in_use = !list_empty(&lock->ast_list);
-	spin_unlock(&dlm->spinlock);
+	spin_unlock(&dlm->ast_lock);
 	if (in_use) {
 	       mlog(ML_ERROR, "lockres %.*s: Someone is calling dlmunlock "
 		    "while waiting for an ast!", res->lockname.len,
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 206a237..7219a86 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -320,9 +320,14 @@
 					struct ocfs2_lock_res *lockres);
 static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
 						int convert);
-#define ocfs2_log_dlm_error(_func, _err, _lockres) do {			\
-	mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n", \
-	     _err, _func, _lockres->l_name);				\
+#define ocfs2_log_dlm_error(_func, _err, _lockres) do {					\
+	if ((_lockres)->l_type != OCFS2_LOCK_TYPE_DENTRY)				\
+		mlog(ML_ERROR, "DLM error %d while calling %s on resource %s\n",	\
+		     _err, _func, _lockres->l_name);					\
+	else										\
+		mlog(ML_ERROR, "DLM error %d while calling %s on resource %.*s%08x\n",	\
+		     _err, _func, OCFS2_DENTRY_LOCK_INO_START - 1, (_lockres)->l_name,	\
+		     (unsigned int)ocfs2_get_dentry_lock_ino(_lockres));		\
 } while (0)
 static int ocfs2_downconvert_thread(void *arg);
 static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb,
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 0773841..946d3c3 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -341,6 +341,9 @@
 	struct ocfs2_node_map		osb_recovering_orphan_dirs;
 	unsigned int			*osb_orphan_wipes;
 	wait_queue_head_t		osb_wipe_event;
+
+	/* used to protect metaecc calculation check of xattr. */
+	spinlock_t osb_xattr_lock;
 };
 
 #define OCFS2_SB(sb)	    ((struct ocfs2_super *)(sb)->s_fs_info)
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index b1cb38f..7ac83a8 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1537,6 +1537,13 @@
 	unlock_buffer(*bh);
 	ll_rw_block(READ, 1, bh);
 	wait_on_buffer(*bh);
+	if (!buffer_uptodate(*bh)) {
+		mlog_errno(-EIO);
+		brelse(*bh);
+		*bh = NULL;
+		return -EIO;
+	}
+
 	return 0;
 }
 
@@ -1747,6 +1754,7 @@
 	INIT_LIST_HEAD(&osb->blocked_lock_list);
 	osb->blocked_lock_count = 0;
 	spin_lock_init(&osb->osb_lock);
+	spin_lock_init(&osb->osb_xattr_lock);
 	ocfs2_init_inode_steal_slot(osb);
 
 	atomic_set(&osb->alloc_stats.moves, 0);
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 915039f..4ddd788 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -82,13 +82,14 @@
 
 #define OCFS2_XATTR_ROOT_SIZE	(sizeof(struct ocfs2_xattr_def_value_root))
 #define OCFS2_XATTR_INLINE_SIZE	80
+#define OCFS2_XATTR_HEADER_GAP	4
 #define OCFS2_XATTR_FREE_IN_IBODY	(OCFS2_MIN_XATTR_INLINE_SIZE \
 					 - sizeof(struct ocfs2_xattr_header) \
-					 - sizeof(__u32))
+					 - OCFS2_XATTR_HEADER_GAP)
 #define OCFS2_XATTR_FREE_IN_BLOCK(ptr)	((ptr)->i_sb->s_blocksize \
 					 - sizeof(struct ocfs2_xattr_block) \
 					 - sizeof(struct ocfs2_xattr_header) \
-					 - sizeof(__u32))
+					 - OCFS2_XATTR_HEADER_GAP)
 
 static struct ocfs2_xattr_def_value_root def_xv = {
 	.xv.xr_list.l_count = cpu_to_le16(1),
@@ -274,10 +275,12 @@
 			       bucket->bu_blocks, bucket->bu_bhs, 0,
 			       NULL);
 	if (!rc) {
+		spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
 		rc = ocfs2_validate_meta_ecc_bhs(bucket->bu_inode->i_sb,
 						 bucket->bu_bhs,
 						 bucket->bu_blocks,
 						 &bucket_xh(bucket)->xh_check);
+		spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
 		if (rc)
 			mlog_errno(rc);
 	}
@@ -310,9 +313,11 @@
 {
 	int i;
 
+	spin_lock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
 	ocfs2_compute_meta_ecc_bhs(bucket->bu_inode->i_sb,
 				   bucket->bu_bhs, bucket->bu_blocks,
 				   &bucket_xh(bucket)->xh_check);
+	spin_unlock(&OCFS2_SB(bucket->bu_inode->i_sb)->osb_xattr_lock);
 
 	for (i = 0; i < bucket->bu_blocks; i++)
 		ocfs2_journal_dirty(handle, bucket->bu_bhs[i]);
@@ -1507,7 +1512,7 @@
 		last += 1;
 	}
 
-	free = min_offs - ((void *)last - xs->base) - sizeof(__u32);
+	free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP;
 	if (free < 0)
 		return -EIO;
 
@@ -2190,7 +2195,7 @@
 		last += 1;
 	}
 
-	free = min_offs - ((void *)last - xs->base) - sizeof(__u32);
+	free = min_offs - ((void *)last - xs->base) - OCFS2_XATTR_HEADER_GAP;
 	if (free < 0)
 		return 0;
 
@@ -2592,8 +2597,9 @@
 
 	if (!ret) {
 		/* Update inode ctime. */
-		ret = ocfs2_journal_access(ctxt->handle, inode, xis->inode_bh,
-					   OCFS2_JOURNAL_ACCESS_WRITE);
+		ret = ocfs2_journal_access_di(ctxt->handle, inode,
+					      xis->inode_bh,
+					      OCFS2_JOURNAL_ACCESS_WRITE);
 		if (ret) {
 			mlog_errno(ret);
 			goto out;
@@ -5060,8 +5066,8 @@
 	xh_free_start = le16_to_cpu(xh->xh_free_start);
 	header_size = sizeof(struct ocfs2_xattr_header) +
 			count * sizeof(struct ocfs2_xattr_entry);
-	max_free = OCFS2_XATTR_BUCKET_SIZE -
-		le16_to_cpu(xh->xh_name_value_len) - header_size;
+	max_free = OCFS2_XATTR_BUCKET_SIZE - header_size -
+		le16_to_cpu(xh->xh_name_value_len) - OCFS2_XATTR_HEADER_GAP;
 
 	mlog_bug_on_msg(header_size > blocksize, "bucket %llu has header size "
 			"of %u which exceed block size\n",
@@ -5094,7 +5100,7 @@
 			need = 0;
 	}
 
-	free = xh_free_start - header_size;
+	free = xh_free_start - header_size - OCFS2_XATTR_HEADER_GAP;
 	/*
 	 * We need to make sure the new name/value pair
 	 * can exist in the same block.
@@ -5127,7 +5133,8 @@
 			}
 
 			xh_free_start = le16_to_cpu(xh->xh_free_start);
-			free = xh_free_start - header_size;
+			free = xh_free_start - header_size
+				- OCFS2_XATTR_HEADER_GAP;
 			if (xh_free_start % blocksize < need)
 				free -= xh_free_start % blocksize;
 
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 3e76bb9..d8bb5c6 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -485,8 +485,10 @@
 			}
 		}
 		unlock_new_inode(inode);
-	} else
+	} else {
 	       module_put(de->owner);
+	       de_put(de);
+	}
 	return inode;
 
 out_ino:
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 767d95a..2d13451 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -107,7 +107,7 @@
 		else
 			kflags = ppage->flags;
 
-		uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) |
+		uflags = kpf_copy_bit(kflags, KPF_LOCKED, PG_locked) |
 			kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
 			kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
 			kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 0b0d236..c7d4b2e 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -76,6 +76,7 @@
 	void (*mode_set)(struct drm_encoder *encoder,
 			 struct drm_display_mode *mode,
 			 struct drm_display_mode *adjusted_mode);
+	struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder);
 	/* detect for DAC style encoders */
 	enum drm_connector_status (*detect)(struct drm_encoder *encoder,
 					    struct drm_connector *connector);
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index c707c15..ff8d27a 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -58,10 +58,10 @@
 	u8 hsync_pulse_width_lo;
 	u8 vsync_pulse_width_lo:4;
 	u8 vsync_offset_lo:4;
-	u8 hsync_pulse_width_hi:2;
-	u8 hsync_offset_hi:2;
 	u8 vsync_pulse_width_hi:2;
 	u8 vsync_offset_hi:2;
+	u8 hsync_pulse_width_hi:2;
+	u8 hsync_offset_hi:2;
 	u8 width_mm_lo;
 	u8 height_mm_lo;
 	u8 height_mm_hi:4;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index dcaa0fd..465d6ba 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -708,6 +708,8 @@
 };
 
 /* This should not be used directly - use rq_for_each_segment */
+#define for_each_bio(_bio)		\
+	for (; _bio; _bio = _bio->bi_next)
 #define __rq_for_each_bio(_bio, rq)	\
 	if ((rq->bio))			\
 		for (_bio = (rq)->bio; _bio; _bio = _bio->bi_next)
diff --git a/include/linux/i2c-dev.h b/include/linux/i2c-dev.h
index 311315b..fd53bfd 100644
--- a/include/linux/i2c-dev.h
+++ b/include/linux/i2c-dev.h
@@ -33,7 +33,7 @@
  */
 #define I2C_RETRIES	0x0701	/* number of times a device address should
 				   be polled when not acknowledging */
-#define I2C_TIMEOUT	0x0702	/* set timeout in jiffies - call with int */
+#define I2C_TIMEOUT	0x0702	/* set timeout in units of 10 ms */
 
 /* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
  * are NOT supported! (due to code brokenness)
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index fcfbfea..c86c3b0 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -361,7 +361,7 @@
 	struct mutex bus_lock;
 	struct mutex clist_lock;
 
-	int timeout;
+	int timeout;			/* in jiffies */
 	int retries;
 	struct device dev;		/* the adapter device */
 
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 194da5a..fe235b6 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -663,7 +663,7 @@
 #define to_ide_device(dev)		container_of(dev, ide_drive_t, gendev)
 
 #define to_ide_drv(obj, cont_type)	\
-	container_of(obj, struct cont_type, kref)
+	container_of(obj, struct cont_type, dev)
 
 #define ide_drv_g(disk, cont_type)	\
 	container_of((disk)->private_data, struct cont_type, driver)
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index f8ff918..e1ff5b1 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -210,6 +210,7 @@
 
 	/* Move the mac addresses to the beginning of the new header. */
 	memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN);
+	skb->mac_header -= VLAN_HLEN;
 
 	/* first, the ethernet type */
 	veth->h_vlan_proto = htons(ETH_P_8021Q);
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index c4f6c10..d2e3cbf 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -194,6 +194,7 @@
 /* FSTS_REG */
 #define DMA_FSTS_PPF ((u32)2)
 #define DMA_FSTS_PFO ((u32)1)
+#define DMA_FSTS_IQE (1 << 4)
 #define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
 
 /* FRCD_REG, 32 bits access */
@@ -328,7 +329,7 @@
 			  unsigned int size_order, u64 type,
 			  int non_present_entry_flush);
 
-extern void qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
+extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
 
 extern void *intel_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
 extern void intel_free_coherent(struct device *, size_t, void *, dma_addr_t);
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h
index 82df317..cbc2f0c 100644
--- a/include/linux/io-mapping.h
+++ b/include/linux/io-mapping.h
@@ -30,11 +30,14 @@
  * See Documentation/io_mapping.txt
  */
 
-/* this struct isn't actually defined anywhere */
-struct io_mapping;
-
 #ifdef CONFIG_HAVE_ATOMIC_IOMAP
 
+struct io_mapping {
+	resource_size_t base;
+	unsigned long size;
+	pgprot_t prot;
+};
+
 /*
  * For small address space machines, mapping large objects
  * into the kernel virtual space isn't practical. Where
@@ -43,23 +46,40 @@
  */
 
 static inline struct io_mapping *
-io_mapping_create_wc(unsigned long base, unsigned long size)
+io_mapping_create_wc(resource_size_t base, unsigned long size)
 {
-	return (struct io_mapping *) base;
+	struct io_mapping *iomap;
+
+	if (!is_io_mapping_possible(base, size))
+		return NULL;
+
+	iomap = kmalloc(sizeof(*iomap), GFP_KERNEL);
+	if (!iomap)
+		return NULL;
+
+	iomap->base = base;
+	iomap->size = size;
+	iomap->prot = pgprot_writecombine(__pgprot(__PAGE_KERNEL));
+	return iomap;
 }
 
 static inline void
 io_mapping_free(struct io_mapping *mapping)
 {
+	kfree(mapping);
 }
 
 /* Atomic map/unmap */
 static inline void *
 io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset)
 {
-	offset += (unsigned long) mapping;
-	return iomap_atomic_prot_pfn(offset >> PAGE_SHIFT, KM_USER0,
-				     __pgprot(__PAGE_KERNEL_WC));
+	resource_size_t phys_addr;
+	unsigned long pfn;
+
+	BUG_ON(offset >= mapping->size);
+	phys_addr = mapping->base + offset;
+	pfn = (unsigned long) (phys_addr >> PAGE_SHIFT);
+	return iomap_atomic_prot_pfn(pfn, KM_USER0, mapping->prot);
 }
 
 static inline void
@@ -71,8 +91,9 @@
 static inline void *
 io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
 {
-	offset += (unsigned long) mapping;
-	return ioremap_wc(offset, PAGE_SIZE);
+	BUG_ON(offset >= mapping->size);
+	resource_size_t phys_addr = mapping->base + offset;
+	return ioremap_wc(phys_addr, PAGE_SIZE);
 }
 
 static inline void
@@ -83,9 +104,12 @@
 
 #else
 
+/* this struct isn't actually defined anywhere */
+struct io_mapping;
+
 /* Create the io_mapping object*/
 static inline struct io_mapping *
-io_mapping_create_wc(unsigned long base, unsigned long size)
+io_mapping_create_wc(resource_size_t base, unsigned long size)
 {
 	return (struct io_mapping *) ioremap_wc(base, size);
 }
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index cf2cb50..9dcf956 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -416,15 +416,6 @@
 				     void *here);
 extern void	      skb_under_panic(struct sk_buff *skb, int len,
 				      void *here);
-extern void	      skb_truesize_bug(struct sk_buff *skb);
-
-static inline void skb_truesize_check(struct sk_buff *skb)
-{
-	int len = sizeof(struct sk_buff) + skb->len;
-
-	if (unlikely((int)skb->truesize < len))
-		skb_truesize_bug(skb);
-}
 
 extern int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
 			int getfrag(void *from, char *to, int offset,
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 6b58367..6f3c603 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -41,13 +41,13 @@
 #ifndef ARCH_HAS_NOCACHE_UACCESS
 
 static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
-				const void __user *from, unsigned long n)
+		const void __user *from, unsigned long n, unsigned long total)
 {
 	return __copy_from_user_inatomic(to, from, n);
 }
 
 static inline unsigned long __copy_from_user_nocache(void *to,
-				const void __user *from, unsigned long n)
+		const void __user *from, unsigned long n, unsigned long total)
 {
 	return __copy_from_user(to, from, n);
 }
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 315bcd3..cc4f453 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -13,6 +13,7 @@
 	struct kref		kref;
 	struct hlist_head	uidhash_table[UIDHASH_SZ];
 	struct user_struct	*creator;
+	struct work_struct	destroyer;
 };
 
 extern struct user_namespace init_user_ns;
diff --git a/include/net/sock.h b/include/net/sock.h
index ce3b5b6..eefeeaf 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -860,7 +860,6 @@
 
 static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
 {
-	skb_truesize_check(skb);
 	sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
 	sk->sk_wmem_queued -= skb->truesize;
 	sk_mem_uncharge(sk, skb->truesize);
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 7908431..076c7c8 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -60,12 +60,25 @@
 	return 0;
 }
 
-void free_user_ns(struct kref *kref)
+/*
+ * Deferred destructor for a user namespace.  This is required because
+ * free_user_ns() may be called with uidhash_lock held, but we need to call
+ * back to free_uid() which will want to take the lock again.
+ */
+static void free_user_ns_work(struct work_struct *work)
 {
-	struct user_namespace *ns;
-
-	ns = container_of(kref, struct user_namespace, kref);
+	struct user_namespace *ns =
+		container_of(work, struct user_namespace, destroyer);
 	free_uid(ns->creator);
 	kfree(ns);
 }
+
+void free_user_ns(struct kref *kref)
+{
+	struct user_namespace *ns =
+		container_of(kref, struct user_namespace, kref);
+
+	INIT_WORK(&ns->destroyer, free_user_ns_work);
+	schedule_work(&ns->destroyer);
+}
 EXPORT_SYMBOL(free_user_ns);
diff --git a/mm/filemap.c b/mm/filemap.c
index 23acefe..60fd567 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1816,14 +1816,14 @@
 static size_t __iovec_copy_from_user_inatomic(char *vaddr,
 			const struct iovec *iov, size_t base, size_t bytes)
 {
-	size_t copied = 0, left = 0;
+	size_t copied = 0, left = 0, total = bytes;
 
 	while (bytes) {
 		char __user *buf = iov->iov_base + base;
 		int copy = min(bytes, iov->iov_len - base);
 
 		base = 0;
-		left = __copy_from_user_inatomic_nocache(vaddr, buf, copy);
+		left = __copy_from_user_inatomic_nocache(vaddr, buf, copy, total);
 		copied += copy;
 		bytes -= copy;
 		vaddr += copy;
@@ -1851,8 +1851,9 @@
 	if (likely(i->nr_segs == 1)) {
 		int left;
 		char __user *buf = i->iov->iov_base + i->iov_offset;
+
 		left = __copy_from_user_inatomic_nocache(kaddr + offset,
-							buf, bytes);
+							buf, bytes, bytes);
 		copied = bytes - left;
 	} else {
 		copied = __iovec_copy_from_user_inatomic(kaddr + offset,
@@ -1880,7 +1881,8 @@
 	if (likely(i->nr_segs == 1)) {
 		int left;
 		char __user *buf = i->iov->iov_base + i->iov_offset;
-		left = __copy_from_user_nocache(kaddr + offset, buf, bytes);
+
+		left = __copy_from_user_nocache(kaddr + offset, buf, bytes, bytes);
 		copied = bytes - left;
 	} else {
 		copied = __iovec_copy_from_user_inatomic(kaddr + offset,
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 0c04615..bf54f8a 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -354,7 +354,7 @@
 			break;
 
 		copied = bytes -
-			__copy_from_user_nocache(xip_mem + offset, buf, bytes);
+			__copy_from_user_nocache(xip_mem + offset, buf, bytes, bytes);
 
 		if (likely(copied > 0)) {
 			status = copied;
diff --git a/mm/shmem.c b/mm/shmem.c
index 19d566c..4103a23 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -169,13 +169,13 @@
  */
 static inline int shmem_acct_size(unsigned long flags, loff_t size)
 {
-	return (flags & VM_ACCOUNT) ?
-		security_vm_enough_memory_kern(VM_ACCT(size)) : 0;
+	return (flags & VM_NORESERVE) ?
+		0 : security_vm_enough_memory_kern(VM_ACCT(size));
 }
 
 static inline void shmem_unacct_size(unsigned long flags, loff_t size)
 {
-	if (flags & VM_ACCOUNT)
+	if (!(flags & VM_NORESERVE))
 		vm_unacct_memory(VM_ACCT(size));
 }
 
@@ -187,13 +187,13 @@
  */
 static inline int shmem_acct_block(unsigned long flags)
 {
-	return (flags & VM_ACCOUNT) ?
-		0 : security_vm_enough_memory_kern(VM_ACCT(PAGE_CACHE_SIZE));
+	return (flags & VM_NORESERVE) ?
+		security_vm_enough_memory_kern(VM_ACCT(PAGE_CACHE_SIZE)) : 0;
 }
 
 static inline void shmem_unacct_blocks(unsigned long flags, long pages)
 {
-	if (!(flags & VM_ACCOUNT))
+	if (flags & VM_NORESERVE)
 		vm_unacct_memory(pages * VM_ACCT(PAGE_CACHE_SIZE));
 }
 
@@ -1515,8 +1515,8 @@
 	return 0;
 }
 
-static struct inode *
-shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
+static struct inode *shmem_get_inode(struct super_block *sb, int mode,
+					dev_t dev, unsigned long flags)
 {
 	struct inode *inode;
 	struct shmem_inode_info *info;
@@ -1537,6 +1537,7 @@
 		info = SHMEM_I(inode);
 		memset(info, 0, (char *)inode - (char *)info);
 		spin_lock_init(&info->lock);
+		info->flags = flags & VM_NORESERVE;
 		INIT_LIST_HEAD(&info->swaplist);
 
 		switch (mode & S_IFMT) {
@@ -1779,9 +1780,10 @@
 static int
 shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 {
-	struct inode *inode = shmem_get_inode(dir->i_sb, mode, dev);
+	struct inode *inode;
 	int error = -ENOSPC;
 
+	inode = shmem_get_inode(dir->i_sb, mode, dev, VM_NORESERVE);
 	if (inode) {
 		error = security_inode_init_security(inode, dir, NULL, NULL,
 						     NULL);
@@ -1920,7 +1922,7 @@
 	if (len > PAGE_CACHE_SIZE)
 		return -ENAMETOOLONG;
 
-	inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
+	inode = shmem_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0, VM_NORESERVE);
 	if (!inode)
 		return -ENOSPC;
 
@@ -2332,7 +2334,7 @@
 	sb->s_flags |= MS_POSIXACL;
 #endif
 
-	inode = shmem_get_inode(sb, S_IFDIR | sbinfo->mode, 0);
+	inode = shmem_get_inode(sb, S_IFDIR | sbinfo->mode, 0, VM_NORESERVE);
 	if (!inode)
 		goto failed;
 	inode->i_uid = sbinfo->uid;
@@ -2574,12 +2576,12 @@
 	return 0;
 }
 
-#define shmem_file_operations ramfs_file_operations
-#define shmem_vm_ops generic_file_vm_ops
-#define shmem_get_inode ramfs_get_inode
-#define shmem_acct_size(a, b) 0
-#define shmem_unacct_size(a, b) do {} while (0)
-#define SHMEM_MAX_BYTES LLONG_MAX
+#define shmem_vm_ops				generic_file_vm_ops
+#define shmem_file_operations			ramfs_file_operations
+#define shmem_get_inode(sb, mode, dev, flags)	ramfs_get_inode(sb, mode, dev)
+#define shmem_acct_size(flags, size)		0
+#define shmem_unacct_size(flags, size)		do {} while (0)
+#define SHMEM_MAX_BYTES				LLONG_MAX
 
 #endif /* CONFIG_SHMEM */
 
@@ -2589,7 +2591,7 @@
  * shmem_file_setup - get an unlinked file living in tmpfs
  * @name: name for dentry (to be seen in /proc/<pid>/maps
  * @size: size to be set for the file
- * @flags: vm_flags
+ * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
  */
 struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
 {
@@ -2623,13 +2625,10 @@
 		goto put_dentry;
 
 	error = -ENOSPC;
-	inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
+	inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, flags);
 	if (!inode)
 		goto close_file;
 
-#ifdef CONFIG_SHMEM
-	SHMEM_I(inode)->flags = (flags & VM_NORESERVE) ? 0 : VM_ACCOUNT;
-#endif
 	d_instantiate(dentry, inode);
 	inode->i_size = size;
 	inode->i_nlink = 0;	/* It is unlinked */
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 903cad4..11a9298 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -323,6 +323,7 @@
 	unsigned long addr;
 	int purged = 0;
 
+	BUG_ON(!size);
 	BUG_ON(size & ~PAGE_MASK);
 
 	va = kmalloc_node(sizeof(struct vmap_area),
@@ -334,6 +335,9 @@
 	addr = ALIGN(vstart, align);
 
 	spin_lock(&vmap_area_lock);
+	if (addr + size - 1 < addr)
+		goto overflow;
+
 	/* XXX: could have a last_hole cache */
 	n = vmap_area_root.rb_node;
 	if (n) {
@@ -365,6 +369,8 @@
 
 		while (addr + size > first->va_start && addr + size <= vend) {
 			addr = ALIGN(first->va_end + PAGE_SIZE, align);
+			if (addr + size - 1 < addr)
+				goto overflow;
 
 			n = rb_next(&first->rb_node);
 			if (n)
@@ -375,6 +381,7 @@
 	}
 found:
 	if (addr + size > vend) {
+overflow:
 		spin_unlock(&vmap_area_lock);
 		if (!purged) {
 			purge_vmap_area_lazy();
@@ -498,6 +505,7 @@
 	static DEFINE_SPINLOCK(purge_lock);
 	LIST_HEAD(valist);
 	struct vmap_area *va;
+	struct vmap_area *n_va;
 	int nr = 0;
 
 	/*
@@ -537,7 +545,7 @@
 
 	if (nr) {
 		spin_lock(&vmap_area_lock);
-		list_for_each_entry(va, &valist, purge_list)
+		list_for_each_entry_safe(va, n_va, &valist, purge_list)
 			__free_vmap_area(va);
 		spin_unlock(&vmap_area_lock);
 	}
@@ -1259,6 +1267,7 @@
 void vunmap(const void *addr)
 {
 	BUG_ON(in_interrupt());
+	might_sleep();
 	__vunmap(addr, 0);
 }
 EXPORT_SYMBOL(vunmap);
@@ -1278,6 +1287,8 @@
 {
 	struct vm_struct *area;
 
+	might_sleep();
+
 	if (count > num_physpages)
 		return NULL;
 
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 55151fa..2adb1a7 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -32,24 +32,14 @@
 {
 	/* Must be called with net_mutex held */
 	struct pernet_operations *ops;
-	int error;
-	struct net_generic *ng;
+	int error = 0;
 
 	atomic_set(&net->count, 1);
+
 #ifdef NETNS_REFCNT_DEBUG
 	atomic_set(&net->use_count, 0);
 #endif
 
-	error = -ENOMEM;
-	ng = kzalloc(sizeof(struct net_generic) +
-			INITIAL_NET_GEN_PTRS * sizeof(void *), GFP_KERNEL);
-	if (ng == NULL)
-		goto out;
-
-	ng->len = INITIAL_NET_GEN_PTRS;
-	rcu_assign_pointer(net->gen, ng);
-
-	error = 0;
 	list_for_each_entry(ops, &pernet_list, list) {
 		if (ops->init) {
 			error = ops->init(net);
@@ -70,24 +60,50 @@
 	}
 
 	rcu_barrier();
-	kfree(ng);
 	goto out;
 }
 
+static struct net_generic *net_alloc_generic(void)
+{
+	struct net_generic *ng;
+	size_t generic_size = sizeof(struct net_generic) +
+		INITIAL_NET_GEN_PTRS * sizeof(void *);
+
+	ng = kzalloc(generic_size, GFP_KERNEL);
+	if (ng)
+		ng->len = INITIAL_NET_GEN_PTRS;
+
+	return ng;
+}
+
 #ifdef CONFIG_NET_NS
 static struct kmem_cache *net_cachep;
 static struct workqueue_struct *netns_wq;
 
 static struct net *net_alloc(void)
 {
-	return kmem_cache_zalloc(net_cachep, GFP_KERNEL);
+	struct net *net = NULL;
+	struct net_generic *ng;
+
+	ng = net_alloc_generic();
+	if (!ng)
+		goto out;
+
+	net = kmem_cache_zalloc(net_cachep, GFP_KERNEL);
+	if (!net)
+		goto out_free;
+
+	rcu_assign_pointer(net->gen, ng);
+out:
+	return net;
+
+out_free:
+	kfree(ng);
+	goto out;
 }
 
 static void net_free(struct net *net)
 {
-	if (!net)
-		return;
-
 #ifdef NETNS_REFCNT_DEBUG
 	if (unlikely(atomic_read(&net->use_count) != 0)) {
 		printk(KERN_EMERG "network namespace not free! Usage: %d\n",
@@ -112,27 +128,28 @@
 	err = -ENOMEM;
 	new_net = net_alloc();
 	if (!new_net)
-		goto out;
+		goto out_err;
 
 	mutex_lock(&net_mutex);
 	err = setup_net(new_net);
-	if (err)
-		goto out_unlock;
-
-	rtnl_lock();
-	list_add_tail(&new_net->list, &net_namespace_list);
-	rtnl_unlock();
-
-
-out_unlock:
+	if (!err) {
+		rtnl_lock();
+		list_add_tail(&new_net->list, &net_namespace_list);
+		rtnl_unlock();
+	}
 	mutex_unlock(&net_mutex);
+
+	if (err)
+		goto out_free;
 out:
 	put_net(old_net);
-	if (err) {
-		net_free(new_net);
-		new_net = ERR_PTR(err);
-	}
 	return new_net;
+
+out_free:
+	net_free(new_net);
+out_err:
+	new_net = ERR_PTR(err);
+	goto out;
 }
 
 static void cleanup_net(struct work_struct *work)
@@ -188,6 +205,7 @@
 
 static int __init net_ns_init(void)
 {
+	struct net_generic *ng;
 	int err;
 
 	printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
@@ -202,6 +220,12 @@
 		panic("Could not create netns workq");
 #endif
 
+	ng = net_alloc_generic();
+	if (!ng)
+		panic("Could not allocate generic netns");
+
+	rcu_assign_pointer(init_net.gen, ng);
+
 	mutex_lock(&net_mutex);
 	err = setup_net(&init_net);
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index da74b84..c6a6b16 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -143,14 +143,6 @@
 	BUG();
 }
 
-void skb_truesize_bug(struct sk_buff *skb)
-{
-	WARN(net_ratelimit(), KERN_ERR "SKB BUG: Invalid truesize (%u) "
-	       "len=%u, sizeof(sk_buff)=%Zd\n",
-	       skb->truesize, skb->len, sizeof(struct sk_buff));
-}
-EXPORT_SYMBOL(skb_truesize_bug);
-
 /* 	Allocate a new skbuff. We do this ourselves so we can fill in a few
  *	'private' fields and also do memory statistics to find all the
  *	[BEEP] leaks.
diff --git a/net/core/sock.c b/net/core/sock.c
index 6f2e133..5f97caa 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -696,7 +696,7 @@
 	if (len < 0)
 		return -EINVAL;
 
-	v.val = 0;
+	memset(&v, 0, sizeof(v));
 
 	switch(optname) {
 	case SO_DEBUG:
@@ -1137,7 +1137,6 @@
 {
 	struct sock *sk = skb->sk;
 
-	skb_truesize_check(skb);
 	atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
 	sk_mem_uncharge(skb->sk, skb->truesize);
 }
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index dda42f0..da2c3b8 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2023,7 +2023,6 @@
 		last_lost = tp->snd_una;
 	}
 
-	/* First pass: retransmit lost packets. */
 	tcp_for_write_queue_from(skb, sk) {
 		__u8 sacked = TCP_SKB_CB(skb)->sacked;
 
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 45eb0ae..2d5ece7 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -10,7 +10,7 @@
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.27';
+my $V = '0.28';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -110,7 +110,8 @@
 			__iomem|
 			__must_check|
 			__init_refok|
-			__kprobes
+			__kprobes|
+			__ref
 		}x;
 our $Attribute	= qr{
 			const|
@@ -1240,7 +1241,8 @@
 			$realfile =~ s@^([^/]*)/@@;
 
 			$p1_prefix = $1;
-			if ($tree && $p1_prefix ne '' && -e "$root/$p1_prefix") {
+			if (!$file && $tree && $p1_prefix ne '' &&
+			    -e "$root/$p1_prefix") {
 				WARN("patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
 			}
 
@@ -1583,9 +1585,9 @@
 		}
 # TEST: allow direct testing of the attribute matcher.
 		if ($dbg_attr) {
-			if ($line =~ /^.\s*$Attribute\s*$/) {
+			if ($line =~ /^.\s*$Modifier\s*$/) {
 				ERROR("TEST: is attr\n" . $herecurr);
-			} elsif ($dbg_attr > 1 && $line =~ /^.+($Attribute)/) {
+			} elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
 				ERROR("TEST: is not attr ($1 is)\n". $herecurr);
 			}
 			next;
@@ -1657,7 +1659,7 @@
 
 # * goes on variable not on type
 		# (char*[ const])
-		if ($line =~ m{\($NonptrType(\s*\*[\s\*]*(?:$Modifier\s*)*)\)}) {
+		if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) {
 			my ($from, $to) = ($1, $1);
 
 			# Should start with a space.
@@ -1672,7 +1674,7 @@
 			if ($from ne $to) {
 				ERROR("\"(foo$from)\" should be \"(foo$to)\"\n" .  $herecurr);
 			}
-		} elsif ($line =~ m{\b$NonptrType(\s*\*[\s\*]*(?:$Modifier\s*)?)($Ident)}) {
+		} elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) {
 			my ($from, $to, $ident) = ($1, $1, $2);
 
 			# Should start with a space.
@@ -1685,8 +1687,8 @@
 			# Modifiers should have spaces.
 			$to =~ s/(\b$Modifier$)/$1 /;
 
-			#print "from<$from> to<$to>\n";
-			if ($from ne $to) {
+			#print "from<$from> to<$to> ident<$ident>\n";
+			if ($from ne $to && $ident !~ /^$Modifier$/) {
 				ERROR("\"foo${from}bar\" should be \"foo${to}bar\"\n" .  $herecurr);
 			}
 		}
@@ -1885,11 +1887,11 @@
 					if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
 						ERROR("space required before that '$op' $at\n" . $hereptr);
 					}
-					if ($op eq '*' && $cc =~/\s*const\b/) {
+					if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
 						# A unary '*' may be const
 
 					} elsif ($ctx =~ /.xW/) {
-						ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+						ERROR("Aspace prohibited after that '$op' $at\n" . $hereptr);
 					}
 
 				# unary ++ and unary -- are allowed no space on one side.
@@ -2560,7 +2562,7 @@
 		if ($line =~ /\bin_atomic\s*\(/) {
 			if ($realfile =~ m@^drivers/@) {
 				ERROR("do not use in_atomic in drivers\n" . $herecurr);
-			} else {
+			} elsif ($realfile !~ m@^kernel/@) {
 				WARN("use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
 			}
 		}
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c
index a466443..2fa9299 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -157,7 +157,7 @@
 		while (dst_frames1 > 0) {
 			S1 = S2;
 			if (src_frames1-- > 0) {
-				S1 = *src;
+				S2 = *src;
 				src += src_step;
 			}
 			if (pos & ~R_MASK) {
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 3f00ddf..c7c54e7 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -165,7 +165,7 @@
 MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard.");
 
 static struct pci_device_id snd_aw2_ids[] = {
-	{PCI_VENDOR_ID_SAA7146, PCI_DEVICE_ID_SAA7146, PCI_ANY_ID, PCI_ANY_ID,
+	{PCI_VENDOR_ID_SAA7146, PCI_DEVICE_ID_SAA7146, 0, 0,
 	 0, 0, 0},
 	{0}
 };
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 7958006..101a1c1 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1528,6 +1528,7 @@
 	 .ca0151_chip = 1,
 	 .spk71 = 1,
 	 .spdif_bug = 1,
+	 .invert_shared_spdif = 1,	/* digital/analog switch swapped */
 	 .ac97_chip = 1} ,
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
 	 .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]",
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 482fb03..4ae51dc 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -277,18 +277,19 @@
 {
 	struct snd_hwdep *hwdep = dev_get_drvdata(dev);
 	struct hda_codec *codec = hwdep->private_data;
-	char *p;
-	struct hda_verb verb, *v;
+	struct hda_verb *v;
+	int nid, verb, param;
 
-	verb.nid = simple_strtoul(buf, &p, 0);
-	verb.verb = simple_strtoul(p, &p, 0);
-	verb.param = simple_strtoul(p, &p, 0);
-	if (!verb.nid || !verb.verb || !verb.param)
+	if (sscanf(buf, "%i %i %i", &nid, &verb, &param) != 3)
+		return -EINVAL;
+	if (!nid || !verb)
 		return -EINVAL;
 	v = snd_array_new(&codec->init_verbs);
 	if (!v)
 		return -ENOMEM;
-	*v = verb;
+	v->nid = nid;
+	v->verb = verb;
+	v->param = param;
 	return count;
 }
 
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index ed8fcbd..a680be0 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -7017,6 +7017,7 @@
 		case 0x106b3e00: /* iMac 24 Aluminium */
 			board_config = ALC885_IMAC24;
 			break;
+		case 0x106b00a0: /* MacBookPro3,1 - Another revision */
 		case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */
 		case 0x106b00a4: /* MacbookPro4,1 */
 		case 0x106b2c00: /* Macbook Pro rev3 */
@@ -8469,6 +8470,8 @@
 		ALC888_ACER_ASPIRE_4930G),
 	SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
 		ALC888_ACER_ASPIRE_4930G),
+	SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
+		ALC888_ACER_ASPIRE_4930G),
 	SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */
 	SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
 	SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h
index 84131a9..69d87de 100644
--- a/sound/pci/pcxhr/pcxhr.h
+++ b/sound/pci/pcxhr/pcxhr.h
@@ -97,12 +97,12 @@
 	int capture_chips;
 	int fw_file_set;
 	int firmware_num;
-	int is_hr_stereo:1;
-	int board_has_aes1:1;	/* if 1 board has AES1 plug and SRC */
-	int board_has_analog:1;	/* if 0 the board is digital only */
-	int board_has_mic:1;	/* if 1 the board has microphone input */
-	int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */
-	int mono_capture:1;	/* if 1 the board does mono capture */
+	unsigned int is_hr_stereo:1;
+	unsigned int board_has_aes1:1;	/* if 1 board has AES1 plug and SRC */
+	unsigned int board_has_analog:1; /* if 0 the board is digital only */
+	unsigned int board_has_mic:1; /* if 1 the board has microphone input */
+	unsigned int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */
+	unsigned int mono_capture:1; /* if 1 the board does mono capture */
 
 	struct snd_dma_buffer hostport;